# python学习 至此开始
# 学习日期: 2023/10/29 9:49
# 学习者: 任磊


# 导入所需的库
import os
import time
from socket import *
from gmssl import func, sm2, sm3
import pysm4
import string
import random
import threading
import SystemSign
import tkinter as tk
from tkinter import messagebox
from PIL import ImageTk, Image
# import SystemVerify
# import pyautogui
import binascii
import hmac
import hashlib
import secrets
import gmpy2


# 创建密码库调用类
class Crypto_program(object):
    def __init__(self):
        super().__init__()

    sys_time_key = None  # 系统默认生成的临时通行密钥
    self_sm2_public_key = ""  # 用户的SM2公钥
    self_sm2_private_key = ""  # 用户的SM2私钥
    self_sm2_crypto = ""  # 用户自己的SM2加解密体
    self_private_key = ""  # 用户的身份私钥
    self_public_key = ""  # 用户的身份公钥
    self_share_public_key = ""  # 用户的预共享公钥
    self_share_private_key = ""  # 用户的预共享公钥的私钥
    self_share_public_key_sign = "None"  # 用户的预共享公钥的签名
    self_time_key_list = []  # 用户一次性公私钥对列表
    time_public_key = ""  # 用于X3DH主动计算，生成的临时公钥
    # time_private_key = ""  # 用于X3DH主动计算，生成的临时私钥  单因为需要及时删除，故不采用在此定义
    other_get_key_name_list = []  # 已获得公钥的其他用户名列表
    other_get_time_key_list = []  # 已获得的一次性公钥的列表
    other_get_x3dh_key_list = []  # 已获得的x3dh生成密钥的列表
    self_get_x3dh_time_key_list = []  # 为获得x3dh密钥使用的临时私钥对应的公钥
    x3dh_p = 0  # 默认情况下，取默认值
    x3dh_g = 0  # 默认情况下，取默认值
    x3dh_q = 0  # 默认情况下，取默认值
    # 双棘轮算法所需参数
    """
    通过对方新旧密钥的更新比对，将决定用户是否生成新的临时公私钥对
    """
    kdf_chain_random_data = ""  # 双棘轮的中间值
    kdf_dh_self_time_private_key = ""  # 自己的临时私钥
    kdf_dh_self_time_public_key = ""  # 自己的临时公钥
    kdf_dh_other_new_time_public_key = ""  # 对方新临时公钥
    kdf_dh_other_old_time_public_key = ""  # 对方旧临时公钥

    # 随机生成对称密钥的方法(若输入非法，则默认输出 16 字节长度 sm4)
    @staticmethod
    def random_key_born(key_long):
        # 判断输入是否非法
        if type(key_long) == int:
            if int(key_long) > 0:
                pass
            else:
                key_long = - int(key_long)
        else:
            key_long = 16
        # 生成密钥
        words = string.ascii_lowercase + string.ascii_uppercase + string.digits + string.punctuation
        # 根据长度随机采样几个字符，得到一个列表
        chosen = random.sample(words, key_long)
        # 将列表的每个元素，拼接成一个大字符串
        # 赋值密钥
        end_key = "".join(chosen)
        # 返回随机生成的密钥
        return end_key

    # 创建数据可以直接进行SM3哈希的方法（此处直接输入 str型）  返回消息的哈希值
    @staticmethod
    def sm3_data_hash(data):
        # 进行数据类型的判断
        if type(data) is not bytes:
            time_data = func.bytes_to_list(data.encode('utf-8'))
            hash_data = sm3.sm3_hash(time_data)
            # 返回输入值的hash值
            return hash_data
        else:
            pass

    # 对称密钥基础强度检测，合法性检测的方法(long: 限制的最大长度)
    @staticmethod
    def test_key_strong(key, long):
        pass_flag1 = False
        pass_flag2 = False
        # 判断传入数据的合法性
        if type(long) != int:
            long = 8
        else:
            if int(long) < 8:
                long = 8
            else:
                long = int(long)
        # 检测密钥长度
        key_long = key.encode()
        if 8 <= len(key_long) <= long:
            # 检测是否含有数字
            for word1 in key:
                if word1.isalnum():
                    pass_flag1 = True
                    break
            # 检测是否含有字母
            for word2 in key:
                if word2.isalpha():
                    pass_flag2 = True
                    break
            if pass_flag1 is True and pass_flag2 is True:
                return True
            else:
                return False
        else:
            return False

    # 定义 X3DH 协议下的共享密钥生成方法  主动生成  基于离散对数的数学难题
    @staticmethod
    def x3dh_active_create(other_name, other_sm2_public_key, other_public_key, other_share_public_key, other_share_public_key_sign, other_time_public_key):  # 其中参数均为对方的数据
        pass_flag = False
        # print("正在验证对方预共享公钥...")
        Connection_program.show_sever_key_get_text.insert("end", "正在验证对方预共享公钥...\n")
        other_sm2_crypto = Crypto_program.init_sm2_struct(other_sm2_public_key, "")
        # 使用对方的SM2公钥对对方的预共享公钥进行验签
        if other_sm2_crypto.verify(other_share_public_key_sign, sm3.sm3_hash(func.bytes_to_list(other_share_public_key.encode())).encode()):
            # print("对方预共享公钥验证成功")
            Connection_program.show_sever_key_get_text.insert("end", "对方预共享公钥验证成功！\n")
            pass_flag = True
        else:
            # print("\033[91m对方预共享公钥验证失败\033[0m")
            Connection_program.show_sever_key_get_text.insert("end", "对方预共享公钥验证失败！\n")
        # 检测当前用户是否拥有公私钥数据文件
        if os.path.exists("client(3.50)" + Main_program.name + ".txt"):
            pass
        else:
            # 若无公私钥对数据文件，则创建
            Crypto_program.create_client_key(1)
        # 初始化获得用户公私钥对数据
        File_program.get_client_all_key_data()
        if pass_flag is True:
            # 调用获得用户自己密钥对数据的方法
            File_program.get_client_all_key_data()
            # 调用初始化获得 p 的方法
            File_program.init_x3dh_p_g()
            # 生成临时公私钥对
            self_time_private_key, self_time_public_key = Crypto_program.gen_IDkey(Crypto_program.x3dh_g, Crypto_program.x3dh_p)
            # 调用生成自己在X3DH协议下的公私钥对的方法
            dh1 = Crypto_program.dh(Crypto_program.self_private_key, other_share_public_key)  # 己方身份私钥， 对方预签名公钥
            # print("DH1的值为:{}".format(dh1))
            Connection_program.show_sever_key_get_text.insert("end", "DH的值为:{}\n".format(dh1))
            dh2 = Crypto_program.dh(self_time_private_key, other_public_key)  # 己方临时生成公钥对应的私钥， 对方身份公钥
            # print("DH2的值为:{}".format(dh2))
            Connection_program.show_sever_key_get_text.insert("end", "DH2的值为:{}\n".format(dh2))
            dh3 = Crypto_program.dh(self_time_private_key, other_share_public_key)  # 己方临时生成公钥对应的私钥， 对方预签名公钥
            # print("DH3的值为:{}".format(dh3))
            Connection_program.show_sever_key_get_text.insert("end", "DH3的值为:{}\n".format(dh3))
            if other_time_public_key != "NONE":  # 判断一次性公钥是否为空
                dh4 = Crypto_program.dh(self_time_private_key, other_time_public_key)  # 己方临时生成的公钥对应的私钥， 对方一次性公钥
                # print("DH4的值为:{}".format(dh4))
                Connection_program.show_sever_key_get_text.insert("end", "DH4的值为:{}\n".format(dh4))
            else:
                # print("由于对方无一次性公钥，故DH4值为空")
                Connection_program.show_sever_key_get_text.insert("end", "由于对方五一次性公钥，故DH4的值为空\n")
                dh4 = ""
            """
            # 此为测试用数据
            print("本次计算中")
            print("己方身份私钥:{}".format(Crypto_program.self_private_key))
            print("己方身份公钥:{}".format(Crypto_program.self_public_key))
            print("己方的临时私钥:{}".format(self_time_private_key))
            print("己方的临时公钥:{}".format(self_time_public_key))
            print("对方的身份公钥:{}".format(other_public_key))
            print("对方的预共享公钥:{}".format(other_share_public_key))
            print("对方的一次性公钥:{}".format(other_time_public_key))
            """
            dhf = str(dh1) + str(dh2) + str(dh3) + str(dh4)  # 将四次dh计算的值拼接
            sk = Crypto_program.create_sha256_signature(dhf, str(Main_program.name) + other_name)  # 进行摘要计算获得x3dh协议下的协商秘钥
            return True, sk, self_time_public_key  # 返回获得的协密钥,以及对应临时使用的私钥对应的公钥
        else:
            return False, None, None

    # 定义 X3DH 协议下的共享密钥生成的方法  被动生成  基于离散对数的数学难题  通常为计算后的即时通信，故未对计算结果进行保存
    @staticmethod
    def x3dh_passive_create(self_time_public_key, other_name, other_public_key, other_time_public_key):  # 参数依次为 己方一次性公钥，对方身份公钥，对方一次性公钥
        next_flag = False
        self_time_private_key = ""
        # 调用获得用户自己密钥对数据的方法
        File_program.get_client_all_key_data()
        # 调用初始化获得 p 的方法
        File_program.init_x3dh_p_g()
        # 根据传入的我方一次性公钥，找出对应的一次性私钥
        num = len(Crypto_program.self_time_key_list)
        if self_time_public_key != "":
            for i in range(0, num - 1):
                if Crypto_program.self_time_key_list[i] == self_time_public_key:  # 判断是否为目标一次性公钥
                    self_time_private_key = Crypto_program.self_time_key_list[i + 1]  # 获得对应的一次性私钥
                    next_flag = True
                    break
                else:
                    pass
        else:
            next_flag = True
        if next_flag is True:
            # 己方预签名公钥对应的私钥，对方身份公钥
            dh1 = Crypto_program.dh(Crypto_program.self_share_private_key, other_public_key)
            # print("dh1的值为: {}".format(dh1))
            Connection_program.wait_mode_text.insert("end", "dh1的值为:{}\n".format(dh1))
            # 己方身份公钥对应的私钥，对方的临时公钥
            dh2 = Crypto_program.dh(Crypto_program.self_private_key, other_time_public_key)
            # print("dh2的值为: {}".format(dh2))
            Connection_program.wait_mode_text.insert("end", "dh2的值为:{}\n".format(dh2))
            # 己方预签名公钥对应的私钥， 对方的临时公钥
            dh3 = Crypto_program.dh(Crypto_program.self_share_private_key, other_time_public_key)
            # print("dh3的值为: {}".format(dh3))
            Connection_program.wait_mode_text.insert("end", "dh3的值为:{}\n".format(dh3))
            # 己方一次性公钥对应的私钥，对方临时公钥
            if self_time_public_key != "":
                dh4 = Crypto_program.dh(self_time_private_key, other_time_public_key)
                # print("dh4的值为: {}".format(dh4))
                Connection_program.wait_mode_text.insert("end", "dh4的值为:{}\n".format(dh4))
            else:
                dh4 = ""
                # print("d4的值为空")
                Connection_program.wait_mode_text.insert("end", "dh4的值为空\n")
            # 对获得的各个值进行拼接
            dhf = str(dh1) + str(dh2) + str(dh3) + str(dh4)
            # 进行摘要计算获得x3dh协议下的协商秘钥
            sk = Crypto_program.create_sha256_signature(dhf, other_name + str(Main_program.name))
            """
            暂时处于注释状态，测试完成后启用该部分代码
            # 对该次计算损耗的一次性公私钥对进行删除
            if File_program.update_client_all_data(self_time_public_key, self_time_private_key):  # 判断目标一次性公私钥对移除返回结果
                print("本次计算所使用的一次性公私钥对，已从用户公私钥对数据文件中删除")
            else:
                print("\033[91m本次计算所使用的一次性性公私钥对移除失败，\033[0m")
            """
            return True, sk  # 返回计算获得的X3DH协商密钥
        else:
            # print("\033[91m未能找到临时公钥对应的私钥\033[0m")
            Connection_program.ready_text.config(state="normal")
            Connection_program.ready_text.delete("1.0", "end")
            Connection_program.ready_text.insert("end", "未能找到临时公钥对应的私钥！\n")
            Connection_program.ready_text.config(state="normal")
            return False, None

    # 定义双棘轮算法加密函数
    """
    只有当双发交替的发送消息时，kdf棘轮与dh棘轮才会同时转动，即不断地生成临时公私钥对
    单方向的重复发送消息，仅转动kdf棘轮，不会生成新的公私钥对
    """
    @staticmethod
    def kdf_dh_encry_function(data):
        if Crypto_program.kdf_dh_other_new_time_public_key != Crypto_program.kdf_dh_other_old_time_public_key:  # 判断是否获得对方新的公钥
            # 生成临时公私钥对
            Crypto_program.kdf_dh_self_time_private_key, Crypto_program.kdf_dh_self_time_public_key = Crypto_program.gen_IDkey(Crypto_program.x3dh_g, Crypto_program.x3dh_p)
        password = Crypto_program.kdf_chain_random_data
        salt = Crypto_program.dh(Crypto_program.kdf_dh_self_time_private_key, Crypto_program.kdf_dh_other_new_time_public_key)
        time_signal_key = Crypto_program.create_sha256_signature(password, str(salt))
        # 取生成部分的前 16 位作为本次加密的密钥
        en_data = pysm4.encrypt_ecb(data, time_signal_key[0:15])
        # print("本次使用的加密密钥为:{}".format(time_signal_key[0:15]))
        Connection_program.ready_text.config(state="normal")
        Connection_program.ready_text.delete("1.0", "end")
        Connection_program.ready_text.insert("end", "本次使用的加密密钥为:{}".format(time_signal_key[0:15]))
        Connection_program.ready_text.config(state="disabled")
        # 余下部分作为下一次的 password 输入
        Crypto_program.kdf_chain_random_data = time_signal_key[15:64]
        # 更新对方公钥
        Crypto_program.kdf_dh_other_old_time_public_key = Crypto_program.kdf_dh_other_new_time_public_key
        return en_data

    # 定义双棘轮算法解密函数
    @staticmethod
    def kdf_dh_decry_function(en_data):
        password = Crypto_program.kdf_chain_random_data
        salt = Crypto_program.dh(Crypto_program.kdf_dh_self_time_private_key, Crypto_program.kdf_dh_other_new_time_public_key)
        time_signal_key = Crypto_program.create_sha256_signature(password, str(salt))
        data = pysm4.decrypt_ecb(en_data, time_signal_key[0:15])
        # print("本次使用的解密密钥为:{}".format(time_signal_key[0:15]))
        Connection_program.ready_text.config(state="normal")
        Connection_program.ready_text.delete("1.0", "end")
        Connection_program.ready_text.insert("end", "本次使用的解密密钥为:{}".format(time_signal_key[0:15]))
        Connection_program.ready_text.config(state="disabled")
        Crypto_program.kdf_chain_random_data = time_signal_key[15:64]
        # 返回解密后的数据
        return data

    # 创建用户自己公私钥对(包括SM2公私钥对)及相关数据的方法
    @staticmethod
    def create_client_key(mode=1,):  # 参数为: 生成公私钥对使用的p,g的参数，(1 使用默认p,g， 2 重新生成)
        if mode == 1:
            File_program.init_x3dh_p_g()  # 调用 x3dh协议下的 p, g 初始化的方法
            Crypto_program.self_private_key, Crypto_program.self_public_key = Crypto_program.gen_IDkey(Crypto_program.x3dh_g, Crypto_program.x3dh_p)  # 获得用户的身份公私钥对
            Crypto_program.self_share_private_key, Crypto_program.self_share_public_key = Crypto_program.gen_IDkey(Crypto_program.x3dh_g, Crypto_program.x3dh_p)  # 获得用户的预共享公私钥对
            for _ in range(5):
                time_private_key, time_public_key = Crypto_program.gen_IDkey(Crypto_program.x3dh_g, Crypto_program.x3dh_p)  # 获取每次生成的一次性公私钥对
                Crypto_program.self_time_key_list.append(time_public_key)
                Crypto_program.self_time_key_list.append(time_private_key)
            # 调用SM2公私钥对生成并获取的方法
            Crypto_program.sm2_all_key_born()
            # 调用初始化创建sm2加解密体的方法
            Crypto_program.self_sm2_crypto = Crypto_program.init_sm2_struct(Crypto_program.self_sm2_public_key, Crypto_program.self_sm2_private_key)
            # 使用生成的用户SM2私钥对预共享公钥签名
            Crypto_program.self_share_public_key_sign = Crypto_program.self_sm2_crypto.sign(Crypto_program.sm3_data_hash(str(Crypto_program.self_share_public_key)).encode(), Crypto_program.self_sm2_private_key)
            # 调用创建用户公私钥对数据文件的方法
            File_program.create_client_key_file()
        else:
            pass

    # 生成大质数
    @staticmethod
    def gen_prime(longueur):  # Génère un nombre premier suivant sa longueur  # 根据长度生成质数
        nombreAlea = secrets.randbits(longueur)
        while gmpy2.is_prime(nombreAlea, 25) is False:
            nombreAlea = secrets.randbits(longueur)
        prime = nombreAlea
        return prime

    # 生成 p
    @staticmethod
    def gen_safeprime():  # Génère un nombre fortement premier  生成一个强质数
        while True:
            p = Crypto_program.gen_prime(2048)
            if gmpy2.is_prime((p - 1) // 2) is True:
                print("p : ", p)
                print(p.bit_length())
                return p

    # 生成 G
    @staticmethod
    def gen_elementgen(p):  # Génère un élement générateur avec pour paramètre un nombre fortement premier  生成一个带有强烈质数参数的生成器元素
        q = (p - 1) // 2
        while True:
            alpha = secrets.randbits(512)
            if pow(alpha, 2, p) != 1 & pow(alpha, q, p) != 1 & pow(alpha, p - 1, p) == 1:
                print("alpha:", alpha)
                print("alpha^2:", pow(alpha, 2, p))
                print("alpha^q:", pow(alpha, (p - 1) // 2, p))
                print("alpha^p-1:", pow(alpha, p - 1, p))
                return alpha

    # 定义在X3DH协议下生成用户自己的公私钥对的方法
    @staticmethod
    def gen_IDkey(g, p):  # Permet de générer les clés identités.  允许生成身份密钥。
        print("Génération des clés identités.")  # 身份密钥的生成
        # p = int(fetch_from_server("", "Value_P.txt"))
        # g = int(fetch_from_server("", "Value_G.txt"))
        IDpriv = secrets.randbits(2048)
        IDpub = pow(g, IDpriv, p)
        return IDpriv, IDpub

    @staticmethod  # 拼接三次 DH计算的值 获得最终地共享密钥
    def create_sha256_signature(key, message):
        if len(key) % 2 != 0:
            key = key + "0"
        byte_key = binascii.unhexlify(key)
        message = message.encode()
        return hmac.new(byte_key, message, hashlib.sha256).hexdigest().upper()

    # 定义进行一次 DH 计算的方法
    @staticmethod
    def dh(a, b):
        # p = 11476114425077445636913897780729058814788399522553701049280397688323001276391084717487591797788773737035134819088321086678078901084786890698833590212793893
        p = int(Crypto_program.x3dh_p)
        result = pow(int(b), int(a), p)
        return result

    # 定义调用生成随机SM2密钥对的方法
    @staticmethod
    def sm2_all_key_born():
        # 调用相关文件
        os.system("python E:\python练习\pythonProject\connectionSocket\国密SM2随机生成密钥文件.py")
        # 读取用户公钥
        public_key_file = open("random_public_key_data.txt", "r")
        Crypto_program.self_sm2_public_key = public_key_file.read()
        public_key_file.close()
        # 读取用户私钥
        private_key_file = open("random_private_key_data.txt", "r")
        Crypto_program.self_sm2_private_key = private_key_file.read()
        private_key_file.close()

    # 定义初始化创建 sm2 加解密体的方法   返回sm2加解密体
    @staticmethod
    def init_sm2_struct(sm2_public_key, sm2_private_key):
        sm2_crypto = sm2.CryptSM2(sm2_private_key, sm2_public_key)
        return sm2_crypto


# 创建通信类
class Connection_program(object):
    def __init__(self):
        super().__init__()

    # 通信状态
    connect_flag = False
    # 通信端口号
    PORT = 9000
    # 缓冲区大小
    Max_data = 4056
    # 会话状态
    talk_flag = False
    # 当前可进行 X3DH 协议下的通信用户列表
    hang_key_person_list = []
    # 用户程序当前是否可打断标志符号
    client_main_tcb_interrupt_flag = True
    # 客户端用户操作线程中断的标志
    client_main_tcb_interrupt = False
    # 用户端界面线程已中断表示
    client_main_tcb_close = True
    # 关闭客户端接收指令线程标志变量
    client_recv_order_clos = False
    # 注册方法所需参数
    connect_sever_flag = False  # 连接服务端状态
    register_name = ""  # 用户注册名
    register_password_one = ""  # 用户注册密码
    register_password_two = ""  # 用户注册密码确认
    register_button = ""  # 注册按钮
    ready_text = ""  # 就绪提示文本框
    register_socket = ""  # 通信所需的通信体

    # 登录界面所需参数
    login_button = ""  # 登录按钮
    login_name = ""  # 登录用户名
    login_password = ""  # 登录密码
    login_try_time = 0
    login_try_max_time = 4  # 登录最大尝试次数
    login_socket = ""

    # 用户界面所需参数
    interface_public_chat_button = ""
    interface_hang_key_button = ""
    interface_get_key_button = ""
    interface_have_key_button = ""
    interface_private_room_button = ""
    interface_wait_button = ""

    # 公共聊天室界面所需参数
    public_chat_text = ""  # 聊天数据框
    public_chat_entry = ""  # 消息输入框
    public_chat_send_button = ""  # 消息发送按钮
    public_chat_connect_start_button = ""  # 开启通信按钮
    public_chat_connect_close_button = ""  # 结束通信按钮
    public_chat_exit_button = ""  # 退出聊天室模式按钮
    public_chat_connect_flag = False  # 公共聊天室通信中标志

    # 用户查看及上传界面所需参数
    interface_key_sm2_text = ""  # 用户sm2公私钥对
    interface_key_self_text = ""  # 用户身份公私钥对
    interface_key_share_text = ""  # 用户预共享公私钥对
    interface_key_time_text = ""  # 用户一次性公私钥对
    interface_key_send_button = ""  # 用户公钥上传按钮
    interface_key_born_button = ""  # 用户公私钥对生成按钮
    interface_key_exit_button = ""  # 用户退出按钮
    interface_key_ready_flag = False  # 用户是否可以上传公钥数据的标志

    # 服务端公钥及获得公钥展示界面所需参数
    show_sever_key_name_text = ""
    show_sever_key_get_text = ""
    get_key_button = ""  # 发送获取公钥数据按钮
    get_key_num = ""  # 用户目标输入变量
    get_key_num_button = ""  # 用户目标输入按钮
    output_x3dh_key_text = ""  # 用户最终获得x3dh输出栏
    get_key_into_flag = False  # 是否已获得用户名数据标志
    get_key_flag = False  # 用户最终获得公钥的标志

    # 客户端展示已获得的公钥数据展示界面所需的参数
    show_client_key_text = ""  # 数据展示文本框
    show_client_key_mode_text = ""  # 状态显示框
    show_client_key_entry = ""  # 数据输入框
    show_client_key_input_button = ""  # 数据发送按钮
    show_client_key_connect_start_button = ""  # 开启通信按钮
    show_client_key_connect_close_button = ""  # 结束通信按钮
    show_client_key_exit_button = ""  # 退出按钮
    show_client_key_connect_flag = False  # 客户端是否处于通信状态标志

    # 等待模式窗口所需参数
    wait_mode_text = ""  # 消息展示栏
    wait_mode_state_text = ""  # 通信状态栏
    wait_mode_entry = ""  # 输入框
    wait_mode_send_button = ""  # 消息发送按钮
    wait_mode_connect_start_button = ""  # 进入等待按钮
    wait_mode_connect_next_button = ""  # 结束本次通信按钮
    wait_mode_connect_close_button = ""  # 退出等待按钮
    wait_mode_exit_button = ""  # 退出按钮
    wait_mode_alive_flag = False  # 等待模式激活状态标志
    wait_mode_connect_state = 0  # 通信状态标志符  数据说明: 0：未连接到用户， 1：正在判别用户，2：正在与其他用户通信中
    wait_mode_connect_flag = False  # 等待模式通信状态的标志
    # 等待模式标志
    client_wait_mode_flag = False  # 等待模式总启用标志
    client_wait_mode_connect_flag = False  # 用于判断是否与其他用户进行通信连接
    client_wait_mode_x3dh_start_flag = False  # 用于判断是否进行 X3DH 通信验证
    client_wait_mode_ready_flag = False  # 用于判断 X3DH 是否准备完成
    client_wait_mode_x3dh_key = ""  # 用于记录计算在 X3DH 协议下获得的密钥
    client_wait_mode_other_name = ""  # 用于记录对方用户名
    # 聊天室参数
    private_room_mode_flag = False  # 聊天室模式标志
    private_room_talk_flag = False  # 是否处于聊天中标志

    # 聊天室模式窗口所需参数
    private_chat_text = ""  # 消息窗口
    private_chat_member_text = ""  # 房间的成员列表框  此为房主独有的
    private_chat_member_list = ["成员列表", ]  # 房间的成员列表  此为房主独有的
    private_chat_entry = ""  # 消息输入框
    private_chat_send_button = ""  # 消息发送按钮
    private_chat_connect_start_button = ""  # 开启通信的方法  创建房间  或  查询房间
    private_chat_connect_close_button = ""  # 结束通信的按钮
    private_chat_exit_button = ""  # 退出的按钮
    private_chat_room_member_num = 1  # 聊天室成员数量
    private_chat_room_password = "NONE"  # 聊天室口令
    private_chat_host_send_state = 0  # 房主态 发送按钮状态标志
    private_chat_guest_send_state = 0  # 成员态 发送按钮状态标志
    private_chat_room_ready_flag = False  # 房间的参数设置完毕标志
    private_room_host_name_list = []  # 房主名列表  此为成员态独有
    private_room_now_person_num_list = []  # 房间现人数列表  此为成员态独有
    private_room_max_person_num_list = []  # 房间最大容纳人数列表  此为成员态独有
    private_room_encry_list = []  # 房间加密状态列表  此为成员态独有
    """
    private_chat_host_send_state
    0: 无效
    1： 房主态，人数输入
    2： 房主态，密码输入
    3： 房主态，消息发送
    
    private_chat_guest_send_state
    0:无效
    1： 成员态：房间选择
    2： 成员态：密码输入
    3： 成员态：消息发送
    """

    # 设置通信所需的IP配置的函数
    @staticmethod
    def get_host_ip():
        s = socket(AF_INET, SOCK_DGRAM)
        try:
            s.connect(('8.8.8.8', 80))  # 114.114.114.114也是dns地址
            ip = s.getsockname()[0]
        finally:
            s.close()
        return ip

    # 登录界面
    @staticmethod
    def login_window():
        # 使之所需变量参数
        Connection_program.login_name = tk.StringVar()
        Connection_program.login_password = tk.StringVar()
        # 设置窗口参数
        # 登录界面容器
        Window_program.login_frame = tk.Frame(root_window, height=500, width=600, bd=3, padx=15, pady=10)
        Window_program.login_frame.place(anchor="center", relx=0.5, rely=0.5)
        # 登录界面文本
        Connection_program.ready_text = tk.Text(Window_program.login_frame, font=("黑体", 18), fg="red", width=40, height=2, bd=3, padx=10, pady=5)
        Connection_program.ready_text.grid(row=0, columnspan=2, padx=10, pady=10)
        Connection_program.ready_text.config(state="disabled")
        # 提示语
        tk.Label(Window_program.login_frame, text="请输入用户名与用户密码", font=("kaiti", 18), padx=10, pady=10).grid(row=1, columnspan=2, padx=10, pady=10)
        # 用户名
        tk.Label(Window_program.login_frame, text="账户名:", font=("黑体", 15), padx=10, pady=10).grid(row=2, column=0, padx=10, pady=10)
        tk.Entry(Window_program.login_frame, textvariable=Connection_program.login_name, font=("黑体", 13), width=23,).grid(row=2, column=1, padx=10, pady=10)
        # 用户密码
        tk.Label(Window_program.login_frame, text="密码:", font=("黑体", 15), padx=10, pady=10).grid(row=3, column=0, padx=10, pady=10)
        tk.Entry(Window_program.login_frame, textvariable=Connection_program.login_password, show="*", font=("黑体", 13), width=23).grid(row=3, column=1, padx=10, pady=10)
        # 登录按钮
        Connection_program.login_button = tk.Button(Window_program.login_frame, text="登录", font=("黑体", 15), relief="raised", fg="green", padx=5, pady=5, command=Connection_program.start_login_connect)
        Connection_program.login_button.grid(row=4, column=0, padx=10, pady=10)
        # 取消按钮
        tk.Button(Window_program.login_frame, text="取消", fg="red", font=("黑体", 15), anchor="center", padx=5, pady=5, command=Connection_program.login_window_to_start_window).grid(row=4, column=1, padx=10, pady=10)

    # 登录界面转向其他界面的方法
    @staticmethod
    def login_window_to_start_window():
        Window_program.login_frame.destroy()
        Main_program.start_application()

    @staticmethod
    def login_window_to_interface_window():
        Window_program.login_frame.destroy()
        Connection_program.interface_window()

    # 开启通信的方法  登录模式
    @staticmethod
    def start_login_connect():
        connect_able_flag = False
        # 截止本次登录结束，登录按钮失效
        Connection_program.login_button.config(state="disabled")
        # 发送登录请求预处理
        login_name = Connection_program.login_name.get()
        login_password = Connection_program.login_password.get()
        if login_name == "" or login_name == "用户名不能为空！":
            Connection_program.login_name.set("用户名不能为空！")
        else:
            if login_password == "" or login_password == "用户密码不能为空！":
                Connection_program.login_password.set("用户密码不能为空！")
            else:
                connect_able_flag = True
        if Connection_program.login_try_time >= Connection_program.login_try_max_time:  # 判断尝试登录次数
            Connection_program.ready_text.config(state="normal")
            Connection_program.ready_text.delete("1.0", "end")
            Connection_program.ready_text.insert("end", "您的尝试次数已超过限定的 {} 次数，当前已被锁定！".format(Connection_program.login_try_max_time))
            Connection_program.ready_text.config(state="disabled")
            connect_able_flag = False
        if connect_able_flag is True:  # 判断是否可以进行通行
            pass_flag = False  # 登录结果判断标志
            # 一旦启动，改变通信状态
            Connection_program.connect_flag = True
            # 通信部分
            IP = Connection_program.get_host_ip()  # 获得本机的IPV4地址
            PORT = Connection_program.PORT  # 设置端口号
            # 设置网络层协议，传输层协议
            data_socket = socket(AF_INET, SOCK_STREAM)  # IP协议，TCP
            # 尝试进行连接
            try:
                data_socket.connect((IP, PORT))
                # 接收随机验证消息
                random_data = data_socket.recv(Connection_program.Max_data).decode()
                # 发送签名消息
                sign_hash_data = SystemSign.system_sign_message(random_data)
                data_socket.send(sign_hash_data.encode())
                # print("正在尝试连接服务端...")
                Connection_program.ready_text.config(state="normal")
                Connection_program.ready_text.delete("1.0", "end")
                Connection_program.ready_text.insert("end", "正在尝试连接服务端...")
                Connection_program.ready_text.config(state="disabled")
                # 接收验证结果
                result_data = data_socket.recv(Connection_program.Max_data).decode()
                if result_data == "OK":
                    # print("连接服务端成功")
                    data_socket.send("@sever_connect_mode1".encode())  # 发送通信模式  登录模式
                    time.sleep(0.5)
                    # 将用户名发送至客户端
                    data_socket.send(login_name.encode())
                    # 接收来自客户端的用户是否存在判断结果
                    flag = data_socket.recv(Connection_program.Max_data).decode()
                    Connection_program.ready_text.config(state="normal")
                    Connection_program.ready_text.delete("1.0", "end")
                    if flag == "True":
                        # 进行用户密码的验证
                        hash_password = sm3.sm3_hash(func.bytes_to_list(login_password.encode()))  # 获得用户输入密码的 hash 值
                        # 发送用户密码的哈希值至客户端
                        data_socket.send(hash_password.encode())
                        # 接收服务端的判断结果
                        flag = data_socket.recv(Connection_program.Max_data).decode()
                        if flag == "True":
                            # print("登录成功！")
                            Connection_program.ready_text.insert("end", "登录成功！")
                            Main_program.name = login_name  # 更新用户的账户数据
                            Main_program.password = login_password
                            Connection_program.login_try_time = 0
                            pass_flag = True
                        else:
                            # print("\033[91m 登录失败！\033[0m")
                            Connection_program.ready_text.insert("end", "登录失败！")
                            Connection_program.login_try_time += 1
                    else:
                        # print("\033[91m 不存在该用户！\033[0m")
                        Connection_program.ready_text.insert("end", "不存在该用户！")
                        Connection_program.login_try_time += 1
                    Connection_program.ready_text.config(state="disabled")
                else:
                    # print("\033[91m 连接服务端失败 \033[0m")
                    Connection_program.ready_text.config(state="normal")
                    Connection_program.ready_text.delete("1.0", "end")
                    Connection_program.ready_text.insert("end", "连接服务端失败！")
                    Connection_program.ready_text.config(state="disabled")
            except ConnectionRefusedError:  # 检测连接状况
                Connection_program.ready_text.config(state="normal")
                Connection_program.ready_text.delete("1.0", "end")
                Connection_program.ready_text.insert("end", "服务器不在工作状态或维护中!")
                Connection_program.ready_text.config(state="disabled")
                Connection_program.login_button.config(state="normal")
            finally:
                # 判断是否通过登录
                if pass_flag is True:
                    Connection_program.login_socket = data_socket
                    Connection_program.login_window_to_interface_window()  # 改变界面显示
                else:
                    data_socket.close()
                    Connection_program.login_button.config(state="normal")

    # 用户界面窗口
    @staticmethod
    def interface_window():
        # 设置窗口参数
        # 登录界面容器
        Window_program.interface_frame = tk.Frame(root_window, height=500, width=600, bd=3, padx=15, pady=10)
        Window_program.interface_frame.place(anchor="center", relx=0.5, rely=0.5)
        # 提示文本框
        Connection_program.ready_text = tk.Text(Window_program.interface_frame, font=("黑体", 18), fg="red", width=40, height=2, bd=3, padx=10, pady=5)
        Connection_program.ready_text.insert("end", "欢迎您 {}".format(Main_program.name))
        Connection_program.ready_text.pack(side="top", padx=10, pady=10)
        Connection_program.ready_text.config(state="disabled")
        # 公共聊天室按钮
        Connection_program.interface_public_chat_button = tk.Button(Window_program.interface_frame, width=20, height=1, text="进入公共聊天室", fg="green", font=("黑体", 15), anchor="center", padx=5, pady=5, command=Connection_program.interface_window_to_public_chat_room_window)
        Connection_program.interface_public_chat_button.pack(side="top", padx=10, pady=10)
        # 挂载公钥按钮
        Connection_program.interface_hang_key_button = tk.Button(Window_program.interface_frame, width=20, height=1, text="查看及上传公钥", fg="green", font=("黑体", 15), anchor="center", padx=5, pady=5, command=Connection_program.interface_window_to_interface_key_window)
        Connection_program.interface_hang_key_button.pack(side="top", padx=10, pady=10)
        # 获得公钥按钮
        Connection_program.interface_get_key_button = tk.Button(Window_program.interface_frame, width=20, height=1, text="查询及获得公钥", fg="green", font=("黑体", 15), anchor="center", padx=5, pady=5, command=Connection_program.interface_window_to_show_sever_key_window)
        Connection_program.interface_get_key_button.pack(side="top", padx=10, pady=10)
        # 查看已获得的公钥按钮
        Connection_program.interface_have_key_button = tk.Button(Window_program.interface_frame, width=20, height=1, text="查看已获得公钥", fg="green", font=("黑体", 15), anchor="center", padx=5, pady=5, command=Connection_program.interface_window_to_show_client_key_window)
        Connection_program.interface_have_key_button.pack(side="top", padx=10, pady=10)
        # 聊天室按钮
        Connection_program.interface_private_room_button = tk.Button(Window_program.interface_frame, width=20, height=1, text="进入聊天室模式", fg="green", font=("黑体", 15), anchor="center", padx=5, pady=5, command=Connection_program.interface_window_to_private_chat_room_window)
        Connection_program.interface_private_room_button.pack(side="top", padx=10, pady=10)
        # 等待模式按钮
        Connection_program.interface_wait_button = tk.Button(Window_program.interface_frame, width=20, height=1, text="进入等待模式", fg="green", font=("黑体", 15), anchor="center", padx=5, pady=5, command=Connection_program.interface_window_to_wait_mode_window)
        Connection_program.interface_wait_button.pack(side="top", padx=10, pady=10)
        # 退出登录按钮
        tk.Button(Window_program.interface_frame, width=20, height=1, text="退出登录", fg="red", font=("黑体", 15), anchor="center", padx=5, pady=5, command=Connection_program.interface_window_to_start_window).pack(side="top", padx=10, pady=10)

    # 由用户界面转向其他界面
    @staticmethod
    def interface_window_to_start_window():
        # 向服务端发送退出登录提示
        Connection_program.login_socket.send("@sever_connect_end".encode())
        Connection_program.login_socket.close()
        Connection_program.client_main_tcb_close = True
        # 转向初始界面
        Window_program.interface_frame.destroy()
        Main_program.start_application()

    @staticmethod
    def interface_window_to_interface_key_window():
        Window_program.interface_frame.destroy()
        Connection_program.interface_key_window()

    @staticmethod
    def interface_window_to_show_sever_key_window():
        Window_program.interface_frame.destroy()
        Connection_program.show_sever_key_window()

    @staticmethod
    def interface_window_to_show_client_key_window():
        Window_program.interface_frame.destroy()
        Connection_program.show_client_key_window()

    @staticmethod
    def interface_window_to_wait_mode_window():
        Window_program.interface_frame.destroy()
        Connection_program.wait_mode_window()

    @staticmethod
    def interface_window_to_public_chat_room_window():
        Window_program.interface_frame.destroy()
        Connection_program.public_chat_room_window()

    @staticmethod
    def interface_window_to_private_chat_room_window():
        Window_program.interface_frame.destroy()
        Connection_program.private_chat_room_mode_window()

    # 公共聊天室界面
    @staticmethod
    def public_chat_room_window():
        # 设置窗口所需参数
        Window_program.public_chat_room_frame = tk.Frame(root_window, height=500, width=950, bd=3, padx=15, pady=10)
        Window_program.public_chat_room_frame.place(anchor="center", relx=0.5, rely=0.5)
        # 界面标语
        tk.Label(Window_program.public_chat_room_frame, padx=10, pady=10, font=("黑体", 15), text="公共聊天室界面", fg="black", ).grid(row=0, column=0, columnspan=3, padx=10, pady=10, )
        # 聊天数据框
        Connection_program.public_chat_text = tk.Text(Window_program.public_chat_room_frame, height=30, width=100, bd=3, font=("黑体", 10), fg="black", padx=10, pady=10)
        Connection_program.public_chat_text.config(state="disabled")
        Connection_program.public_chat_text.grid(row=1, column=0, columnspan=3, padx=10, pady=10)
        # 提示消息框
        Connection_program.ready_text = tk.Text(Window_program.public_chat_room_frame, height=2, width=70, bd=3, font=("黑体", 15), fg="red", padx=10, pady=10)
        Connection_program.ready_text.config(state="disabled")
        Connection_program.ready_text.grid(row=2, column=0, columnspan=3, padx=10, pady=10)
        # 数据输入框
        Connection_program.public_chat_entry = tk.Entry(Window_program.public_chat_room_frame, width=50, bd=3, font=("黑体", 15), fg="black", )
        Connection_program.public_chat_entry.grid(row=3, column=0, columnspan=2, padx=10, pady=10)
        # 消息发送按钮
        Connection_program.public_chat_send_button = tk.Button(Window_program.public_chat_room_frame, padx=10, pady=10, font=("黑体", 15), text="发送", fg="green", command=Connection_program.public_chat_send_function)
        Connection_program.public_chat_send_button.config(state="disabled")
        Connection_program.public_chat_send_button.grid(row=3, column=2, padx=10, pady=10)
        # 开启通信按钮
        Connection_program.public_chat_connect_start_button = tk.Button(Window_program.public_chat_room_frame, padx=10, pady=10, font=("黑体", 15), text="开启通信", fg="green", command=Connection_program.public_chat_room_connect_start_function)
        Connection_program.public_chat_connect_start_button.grid(row=4, column=0, padx=10, pady=10)
        # 结束通信按钮
        Connection_program.public_chat_connect_close_button = tk.Button(Window_program.public_chat_room_frame, padx=10, pady=10, font=("黑体", 15), text="结束通信", fg="red", command=Connection_program.public_chat_connect_close_function)
        Connection_program.public_chat_connect_close_button.config(state="disabled")
        Connection_program.public_chat_connect_close_button.grid(row=4, column=1, padx=10, pady=10)
        # 退出聊天室模式按钮
        Connection_program.public_chat_exit_button = tk.Button(Window_program.public_chat_room_frame, padx=10, pady=10, font=("黑体", 15), text="退出", fg="red", command=Connection_program.public_chat_room_window_to_interface_window)
        Connection_program.public_chat_exit_button.grid(row=4, column=2, padx=10, pady=10)

    # 由公共聊天室模式返回用户界面的方法
    @staticmethod
    def public_chat_room_window_to_interface_window():
        Window_program.public_chat_room_frame.destroy()
        Connection_program.interface_window()

    # 公共聊天室消息发送的方法
    @staticmethod
    def public_chat_send_function():
        if Connection_program.public_chat_connect_flag is True:
            # 消息发送预处理
            talk_data = Connection_program.public_chat_entry.get()  # 从消息输入框获得消息
            Connection_program.public_chat_entry.delete(0, "end")  # 清空消息输入框
            if talk_data != "":
                if talk_data == "@sever_public_chat_room_exit":
                    pass
                else:
                    talk_data = Main_program.name + ":" + talk_data + "\n"
                    Connection_program.login_socket.send(talk_data.encode())
                    # Connection_program.public_chat_text.insert("end", talk_data)

    # 定义加入公共聊天室的方法
    @staticmethod
    def public_chat_room_connect_start_function():
        data_socket = Connection_program.login_socket
        # 改变相关组件参数
        Connection_program.public_chat_connect_start_button.config(state="disabled")  # 截止本次通信结束，开启通信按钮失效
        Connection_program.public_chat_exit_button.config(state="disabled")  # 退出按钮失效
        Connection_program.public_chat_text.config(state="normal")
        # 向服务端发送请求加入聊天室的方法
        data_socket.send("@sever_public_chat_room_join".encode())
        # 接收来自服务端回复结果
        en_data = data_socket.recv(Connection_program.Max_data).decode()
        Connection_program.ready_text.config(state="normal")
        Connection_program.ready_text.delete("1.0", "end")
        if en_data == "OK":
            # 改变会话状态
            Connection_program.public_chat_connect_flag = True
            # print("已进入多人聊天室！")
            Connection_program.ready_text.insert("end", "已进入公共聊天室！")
            Connection_program.public_chat_text.insert("end", "已进入公共聊天室！\n")
            Connection_program.public_chat_connect_close_button.config(state="normal")  # 结束通信按钮生效
            Connection_program.public_chat_send_button.config(state="normal")  # 消息发送按钮生效
            # 创建在公共聊天室下的接收消息多线程
            th = threading.Thread(target=Connection_program.public_talk_recv, )
            th.start()  # 启用多线程
        else:
            # print("\033[91m进入多人聊天室失败\033[0m")
            Connection_program.ready_text.insert("end", "进入公共聊天室失败！")
            Connection_program.public_chat_text.insert("end", "进入公共聊天室失败！\n")
            Connection_program.public_chat_text.config(state="disabled")
            Connection_program.public_chat_exit_button.config(state="normal")  # 退出按钮生效
            Connection_program.public_chat_connect_start_button.config(state="normal")  # 通信开启按钮生效
        Connection_program.ready_text.config(state="disabled")

    # 结束公共聊天室通信的方法
    @staticmethod
    def public_chat_connect_close_function():
        if Connection_program.public_chat_connect_flag is True:
            Connection_program.login_socket.send("@sever_public_chat_room_exit".encode())  # 发送退出请求
            Connection_program.public_chat_connect_close_button.config(state="disabled")  # 结束通信按钮失效
            Connection_program.public_chat_send_button.config(state="disabled")  # 消息发送按钮失效

    # 定义接收公用聊天信息的方法
    @staticmethod
    def public_talk_recv():
        Connection_program.public_chat_text.insert("end", "已开始接收消息\n")
        while True:
            talk_data = Connection_program.login_socket.recv(Connection_program.Max_data).decode()
            if talk_data == "@client_public_chat_room_exit":
                Connection_program.public_chat_connect_flag = False
                Connection_program.public_chat_text.insert("end", "已退出公共聊天室！\n")
                Connection_program.public_chat_exit_button.config(state="normal")  # 退出按钮生效
                Connection_program.public_chat_connect_start_button.config(state="normal")  # 开启通信按钮生效
                Connection_program.public_chat_text.config(state="disabled")
                Connection_program.ready_text.config(state="normal")
                Connection_program.ready_text.delete("1.0", "end")
                Connection_program.ready_text.insert("end", "本次通信已结束")
                Connection_program.ready_text.config(state="disabled")
                break
            else:
                talk_data = talk_data + "\n"
                Connection_program.public_chat_text.insert("end", talk_data)

    # 用户查看自己公私钥对以及上传的方法
    @staticmethod
    def interface_key_window():
        # 初始设置参数
        Connection_program.interface_key_ready_flag = False
        # 设置窗口参数
        Window_program.interface_key_frame = tk.Frame(root_window, height=500, width=900, bd=3, padx=15, pady=10, )
        Window_program.interface_key_frame.place(anchor="center", relx=0.5, rely=0.5)

        # 窗口提示标签
        tk.Label(Window_program.interface_key_frame, fg="blue", font=("黑体", 15), padx=10, pady=5, text="用户 {} 的公私钥数据界面".format(Main_program.name)).grid(row=0, column=0, columnspan=3, padx=10, pady=10)
        # sm2公私钥对标签
        tk.Label(Window_program.interface_key_frame, height=1, width=20, fg="red", font=("黑体", 15), bd=3, padx=10, pady=5, text="用户SM2公私钥对:", ).grid(row=1, column=0, padx=10, pady=10)
        # sm2公钥展示框
        Connection_program.interface_key_sm2_text = tk.Text(Window_program.interface_key_frame, height=5, width=65, fg="black", font=("黑体", 10), bd=3, padx=10, pady=5, )
        Connection_program.interface_key_sm2_text.config(state="disabled")
        Connection_program.interface_key_sm2_text.grid(row=1, column=1, columnspan=2, padx=10, pady=10)

        # 身份公私钥对标签
        tk.Label(Window_program.interface_key_frame, height=1, width=20, fg="red", font=("黑体", 15), bd=3, padx=10, pady=5, text="用户身份公私钥对:", ).grid(row=2, column=0, padx=10, pady=10)
        # 身份公私钥对展示框
        Connection_program.interface_key_self_text = tk.Text(Window_program.interface_key_frame, height=5, width=65, fg="black", font=("黑体", 10), bd=3, padx=10, pady=5, )
        Connection_program.interface_key_self_text.config(state="disabled")
        Connection_program.interface_key_self_text.grid(row=2, column=1, columnspan=2, padx=10, pady=10)

        # 预共享公私钥对标签
        tk.Label(Window_program.interface_key_frame, height=1, width=20, fg="red", font=("黑体", 15), bd=3, padx=10, pady=5, text="用户预共享公私钥对:", ).grid(row=3, column=0, padx=10, pady=10)
        # 预共享公私钥对展示框
        Connection_program.interface_key_share_text = tk.Text(Window_program.interface_key_frame, height=5, width=65, fg="black", font=("黑体", 10), bd=3, padx=10, pady=5, )
        Connection_program.interface_key_share_text.config(state="disabled")
        Connection_program.interface_key_share_text.grid(row=3, column=1, columnspan=2, padx=10, pady=10)

        # 一次性公私钥对标签
        tk.Label(Window_program.interface_key_frame, height=1, width=20, fg="red", font=("黑体", 15), bd=3, padx=10, pady=5, text="用户一次性公私钥对:", ).grid(row=4, column=0, padx=10, pady=10)
        # 用户一次性公私钥对展示框
        Connection_program.interface_key_time_text = tk.Text(Window_program.interface_key_frame, height=15, width=65, fg="black", font=("黑体", 10), bd=3, padx=10, pady=5, )
        Connection_program.interface_key_time_text.config(state="disabled")
        Connection_program.interface_key_time_text.grid(row=4, column=1, columnspan=2, padx=10, pady=10)

        # 消息提示框
        Connection_program.ready_text = tk.Text(Window_program.interface_key_frame, height=1, width=70, fg="red", font=("黑体", 15), bd=3, padx=10, pady=5, )
        Connection_program.ready_text.config(state="disabled")
        Connection_program.ready_text.grid(row=5, column=0, columnspan=3, padx=10, pady=10)

        # 公私钥对生成按钮
        Connection_program.interface_key_born_button = tk.Button(Window_program.interface_key_frame, text="生成公私钥对", fg="green", font=("黑体", 15), anchor="center", padx=5, pady=5, command=Connection_program.interface_key_create_key)
        Connection_program.interface_key_born_button.config(state="disabled")
        Connection_program.interface_key_born_button.grid(row=6, column=0, padx=10, pady=10)

        # 公钥上传按钮
        Connection_program.interface_key_send_button = tk.Button(Window_program.interface_key_frame, text="上传公钥", fg="green", font=("黑体", 15), anchor="center", padx=5, pady=5, command=Connection_program.apply_hang_key)
        Connection_program.interface_key_send_button.config(state="disabled")
        Connection_program.interface_key_send_button.grid(row=6, column=1, padx=10, pady=10)

        # 退出按钮
        Connection_program.interface_key_exit_button = tk.Button(Window_program.interface_key_frame, text="退出", fg="red", font=("黑体", 15), anchor="center", padx=5, pady=5, command=Connection_program.interface_key_window_to_interface_window)
        Connection_program.interface_key_exit_button.grid(row=6, column=2, padx=10, pady=10)

        # 调用用户公私钥对获得的方法
        Connection_program.interface_key_get_client_all_key()

    # 获得用户公私钥对的二次方法
    @staticmethod
    def interface_key_get_client_all_key():
        # 修改组件参数
        Connection_program.ready_text.config(state="normal")
        Connection_program.ready_text.delete("1.0", "end")
        Connection_program.interface_key_sm2_text.config(state="normal")
        Connection_program.interface_key_self_text.config(state="normal")
        Connection_program.interface_key_share_text.config(state="normal")
        Connection_program.interface_key_time_text.config(state="normal")
        if File_program.get_client_all_key_data():
            # 录入并显示用户的sm2公私钥对
            Connection_program.interface_key_sm2_text.insert("end", "用户的SM2公钥为:")
            Connection_program.interface_key_sm2_text.insert("end", Crypto_program.self_sm2_public_key)
            Connection_program.interface_key_sm2_text.insert("end", "\n")
            Connection_program.interface_key_sm2_text.insert("end", "用户的SM2私钥为:")
            Connection_program.interface_key_sm2_text.insert("end", Crypto_program.self_sm2_private_key)
            # 录入并显示用户的身份公私钥对
            Connection_program.interface_key_self_text.insert("end", "用户的身份公钥为:")
            Connection_program.interface_key_self_text.insert("end", Crypto_program.self_public_key)
            Connection_program.interface_key_self_text.insert("end", "\n")
            Connection_program.interface_key_self_text.insert("end", "用户的身份私钥为:")
            Connection_program.interface_key_self_text.insert("end", Crypto_program.self_private_key)
            # 录入并显示用户的预共享公私钥对
            Connection_program.interface_key_share_text.insert("end", "用户的预共享公钥为:")
            Connection_program.interface_key_share_text.insert("end", Crypto_program.self_share_public_key)
            Connection_program.interface_key_share_text.insert("end", "\n")
            Connection_program.interface_key_share_text.insert("end", "用户的预共享私钥为:")
            Connection_program.interface_key_share_text.insert("end", Crypto_program.self_share_private_key)
            Connection_program.interface_key_share_text.insert("end", "\n")
            Connection_program.interface_key_share_text.insert("end", "用户的预共享公钥的签名为:")
            Connection_program.interface_key_share_text.insert("end", Crypto_program.self_share_public_key_sign)
            # 录入并显示用户的一次性公私钥对
            key_num = len(Crypto_program.self_time_key_list)
            for i in range(0, int(key_num/2 - 1), 2):
                Connection_program.interface_key_time_text.insert("end", "用户的一次性公钥为:")
                Connection_program.interface_key_time_text.insert("end", Crypto_program.self_time_key_list[i])
                Connection_program.interface_key_time_text.insert("end", "\n")
                Connection_program.interface_key_time_text.insert("end", "用户的一次性私钥为:")
                Connection_program.interface_key_time_text.insert("end", Crypto_program.self_time_key_list[i+1])
                Connection_program.interface_key_time_text.insert("end", "\n")
            Connection_program.interface_key_send_button.config(state="normal")  # 上传公钥按钮生效
            Connection_program.ready_text.insert("end", "用户公私钥对数据获取完成！")
        else:
            Connection_program.ready_text.insert("end", "您当前暂无公私钥对！")
            Connection_program.interface_key_born_button.config(state="normal")  # 公私钥对生成按钮生效
        Connection_program.ready_text.config(state="disabled")
        Connection_program.interface_key_sm2_text.config(state="disabled")
        Connection_program.interface_key_self_text.config(state="disabled")
        Connection_program.interface_key_share_text.config(state="disabled")
        Connection_program.interface_key_time_text.config(state="disabled")

    # 由查看公私钥对及上传窗口 返回 用户窗口的方法
    @staticmethod
    def interface_key_window_to_interface_window():
        Window_program.interface_key_frame.destroy()
        Connection_program.interface_window()

    # 用户公私钥数据生成的方法
    @staticmethod
    def interface_key_create_key():
        Connection_program.interface_key_born_button.config(state="disabled")  # 生成公私钥对按钮失效
        Connection_program.interface_key_exit_button.config(state="disabled")  # 退出按钮失效
        if File_program.get_client_all_key_data():
            pass
        else:
            # 调用用户公私钥数据文件生成的方法
            Crypto_program.create_client_key()
            # 再次显示用户公私钥数据
            Connection_program.interface_key_get_client_all_key()
        Connection_program.interface_key_send_button.config(state="normal")  # 上传公私钥对按钮生效
        Connection_program.interface_key_exit_button.config(state="normal")  # 退出按钮失效

    # 定义用户向服务端请求挂载公钥的方法
    @staticmethod
    def apply_hang_key():
        Connection_program.interface_key_send_button.config(state="disabled")  # 公钥上传按钮失效
        Connection_program.interface_key_exit_button.config(state="disabled")  # 退出按钮失效
        data_socket = Connection_program.login_socket
        # print("正在挂载公钥中...")
        Connection_program.ready_text.config(state="normal")
        Connection_program.ready_text.delete("1.0", "end")
        Connection_program.ready_text.insert("end", "正在上传公钥中...")
        Connection_program.ready_text.config(state="disabled")
        # 发送请求挂载公钥指令
        data_socket.send("@sever_hang_key".encode())
        # 调用初始化获得用户公私钥数据的方法
        if File_program.get_client_all_key_data():  # 判断该用户的公私钥对数据文件是否存在
            pass
        else:
            Crypto_program.create_client_key(1)  # 调用相关方法重建该用户的公私钥对数据文件
            File_program.get_client_all_key_data()  # 再次调用获得用户公私钥对
        data_socket.send(str(Crypto_program.self_sm2_public_key).encode())  # 发送用户SM2公钥
        time.sleep(0.1)  # 延迟，防止粘包
        data_socket.send(str(Crypto_program.self_public_key).encode())  # 发送身份公钥
        time.sleep(0.1)  # 延迟，防止粘包
        data_socket.send(str(Crypto_program.self_share_public_key).encode())  # 发送预共享公钥
        time.sleep(0.1)  # 延迟，防止粘包
        data_socket.send(str(Crypto_program.self_share_public_key_sign).encode())  # 发送预共享公钥的签名
        time.sleep(0.1)  # 延迟，防止粘包
        for item in range(0, len(Crypto_program.self_time_key_list)):  # 遍历发送一次性公钥
            time.sleep(0.1)  # 延迟，防止粘包
            if item % 2 != 0:  # 间隔发送，确保发送的是用户的一次性公钥
                continue
            else:
                data_socket.send(str(Crypto_program.self_time_key_list[item]).encode())
        time.sleep(0.1)  # 延迟，防止粘包
        data_socket.send("@sever_key_end".encode())  # 发送公钥发送完毕提示消息
        end_flag = data_socket.recv(Connection_program.Max_data).decode()  # 接收来自服务端的完成消息
        Connection_program.ready_text.config(state="normal")
        Connection_program.ready_text.delete("1.0", "end")
        if end_flag == "OK":
            # print("公钥上传成功!")
            Connection_program.ready_text.insert("end", "公钥上传成功！")
        else:
            # print("\033[91m公钥上传失败！\033[0m")
            Connection_program.ready_text.insert("end", "公钥上传失败！")
        Connection_program.ready_text.config(state="disabled")
        Connection_program.interface_key_exit_button.config(state="normal")  # 退出按钮生效

    # 服务端公钥及获得公钥展示界面窗口
    @staticmethod
    def show_sever_key_window():
        # 初始设置
        Connection_program.get_key_flag = False
        Connection_program.get_key_into_flag = False
        # 初始设置所需变量
        Connection_program.get_key_num = tk.StringVar()
        # 设置容器
        Window_program.show_sever_key_frame = tk.Frame(root_window, height=500, width=900, bd=3, padx=15, pady=10)
        Window_program.show_sever_key_frame.place(anchor="center", relx=0.5, rely=0.5)

        # 窗口提示标签
        tk.Label(Window_program.show_sever_key_frame, fg="blue", font=("黑体", 15), padx=10, pady=5, text="获得公钥数据界面").grid(row=0, column=0, columnspan=3, padx=10, pady=10)

        # 纵向1
        # 服务端公钥用户名标签
        tk.Label(Window_program.show_sever_key_frame, height=1, width=20, fg="red", font=("黑体", 15), bd=3, padx=10, pady=5, text="当前可获得公钥的用户名").grid(row=1, column=0, padx=10, pady=10)
        # 服务端公钥用户名栏
        Connection_program.show_sever_key_name_text = tk.Text(Window_program.show_sever_key_frame, height=20, width=20, bd=3, font=("黑体", 15), fg="black", padx=10, pady=5)
        Connection_program.show_sever_key_name_text.grid(row=2, rowspan=4, column=0, padx=10, pady=10)
        Connection_program.show_sever_key_name_text.config(state="disabled")
        # 消息提示栏
        Connection_program.ready_text = tk.Text(Window_program.show_sever_key_frame, height=2, width=20, bd=3, font=("黑体", 15), fg="red", padx=10, pady=5)
        Connection_program.ready_text.grid(row=6, column=0, padx=10, pady=10)
        Connection_program.ready_text.config(state="disabled")

        # 纵向2
        # 客户端获得公钥标签
        tk.Label(Window_program.show_sever_key_frame,  height=1, width=40, fg="red", font=("黑体", 15), bd=3, padx=10, pady=5, text="公钥计算及结果显示").grid(row=1, column=1, columnspan=2, padx=10, pady=10)
        # 客户端获得公钥计算及结果栏
        Connection_program.show_sever_key_get_text = tk.Text(Window_program.show_sever_key_frame, width=60, height=15, bd=3, font=("黑体", 10), fg="red", padx=10, pady=5)
        Connection_program.show_sever_key_get_text.grid(row=2, column=1, columnspan=2, padx=10, pady=10)
        Connection_program.show_sever_key_get_text.config(state="disabled")
        # 提示标签
        tk.Label(Window_program.show_sever_key_frame,  height=2, width=30, bd=3,  text="请输入目标用户序号以获取公钥", fg="black", font=("黑体", 15), anchor="center", padx=5, pady=5, ).grid(row=3, column=1, columnspan=2,  padx=10, pady=10)
        # 输入序号栏
        tk.Entry(Window_program.show_sever_key_frame, width=10,  font=("黑体", 15), fg="red", textvariable=Connection_program.get_key_num).grid(row=4, column=1, padx=10, pady=10)
        # 输入确定按钮
        Connection_program.get_key_num_button = tk.Button(Window_program.show_sever_key_frame, height=1, width=10,  text="确定", fg="red", font=("黑体", 15), anchor="center", padx=5, pady=5, command=Connection_program.get_hang_key)
        Connection_program.get_key_num_button.grid(row=4, column=2, padx=10, pady=10)
        # 最终获得X3DH协商密钥标签
        tk.Label(Window_program.show_sever_key_frame, height=2, width=20, bd=3,  text="X3DH协商密钥为:", fg="blue", font=("黑体", 15), anchor="center", padx=5, pady=5, ).grid(row=5, column=1, padx=10, pady=10)
        # 最终获得X3DH协商密钥输出栏
        Connection_program.output_x3dh_key_text = tk.Text(Window_program.show_sever_key_frame, height=3, width=20, bd=3, font=("黑体", 15), fg="red", padx=10, pady=5)
        Connection_program.output_x3dh_key_text.grid(row=5, column=2, padx=10, pady=10)
        # 获得公钥按钮
        Connection_program.get_key_button = tk.Button(Window_program.show_sever_key_frame,  text="获取公钥", fg="green", font=("黑体", 15), anchor="center", padx=5, pady=5, command=Connection_program.search_hang_key)
        Connection_program.get_key_button.grid(row=6, column=1, padx=10, pady=10)
        # 退出按钮
        tk.Button(Window_program.show_sever_key_frame,  text="退出", fg="red", font=("黑体", 15), anchor="center", padx=5, pady=5, command=Connection_program.show_sever_key_window_to_interface_window).grid(row=6, column=2, padx=10, pady=10)

    # 服务端公钥及获得公钥展示界面 转向 用户界面
    @staticmethod
    def show_sever_key_window_to_interface_window():
        if Connection_program.get_key_flag is True:  # 判断用户是否发送了公钥获取请求
            Connection_program.login_socket.send("@sever_get_client_key_exit".encode())
        Window_program.show_sever_key_frame.destroy()
        Connection_program.interface_window()

    # 定义查询服务端已挂载公钥情况以及获取的方法
    @staticmethod
    def search_hang_key():
        # 成功获取用户公钥数据后，本次界面下获取公钥数据按钮不再生效
        Connection_program.get_key_button.config(state="disabled")
        Connection_program.get_key_into_flag = True
        data_socket = Connection_program.login_socket
        # 初始化读取用户已获得的公钥数据
        if File_program.get_client_get_key_list_file(Main_program.name):
            pass
        else:
            # print("\033[91m用户数据读取异常\033[0m")
            Connection_program.ready_text.config(state="normal")
            Connection_program.ready_text.delete("1.0", "end")
            Connection_program.ready_text.insert("end", "用户数据读取异常！")
        data_socket.send("@sever_get_key".encode())  # 向服务端发送查询已挂载公钥的请求指令
        Connection_program.get_key_flag = True  # 一旦发送请求，改变状态
        ready_flag = data_socket.recv(Connection_program.Max_data).decode()  # 接收来自服务端的准备信息
        if ready_flag == "OK":  # 判断服务端回应
            pass_flag = True
        else:
            # print("\033[91m当前服务端不存在已挂载公钥！\033[0m")
            Connection_program.show_sever_key_name_text.config(state="normal")
            Connection_program.show_sever_key_name_text.delete("1.0", "end")
            Connection_program.show_sever_key_name_text.insert("end", "当前服务端不存在已挂载公钥!")
            Connection_program.show_sever_key_name_text.config(state="disabled")
            pass_flag = False
        if pass_flag is True:  # 判断接下来是否继续执行
            Connection_program.show_sever_key_name_text.config(state="normal")
            Connection_program.show_sever_key_name_text.delete("1.0", "end")
            hang_key_num = data_socket.recv(Connection_program.Max_data).decode()  # 接收来自服务端的已挂载公钥数量
            hang_key_num = int(hang_key_num)
            if hang_key_num <= 0:
                # print("\033[91m数据异常！\033[0m")
                Connection_program.show_sever_key_name_text.insert("end", "数据异常！")
            else:
                # print("当前服务端已挂载公钥的用户数量为:{}".format(hang_key_num))
                Connection_program.show_sever_key_name_text.insert("end", "当前服务端已挂载公钥的用户数量为:{}\n".format(hang_key_num))
                Connection_program.hang_key_person_list.clear()  # 清空列表 防止重复
                for item in range(0, hang_key_num):  # 依次接受来自服务端的已挂载公钥的用户名列表
                    name = data_socket.recv(Connection_program.Max_data).decode()  # 接收来自服务端的已挂载公钥的用户名
                    Connection_program.hang_key_person_list.append(name)  # 将用户名添加至可通信用户列表
            end_flag = data_socket.recv(Connection_program.Max_data).decode()  # 接收结束校验数据
            if end_flag == "@client_name_end":
                # 展示服务端已挂载公钥的用户
                # print("服务端已挂载公钥的用户有:")
                num_list = 1
                for name in Connection_program.hang_key_person_list:
                    # print(str(num_list), " ", name)
                    Connection_program.show_sever_key_name_text.insert("end", "{} {}\n".format(num_list, name))
                    num_list += 1
                Connection_program.show_sever_key_name_text.config(state="disabled")
                # print("输入对应用户序号以获得对应的公钥数据，或者输入(退出)")
                Connection_program.ready_text.config(state="normal")
                Connection_program.ready_text.delete("1.0", "end")
                Connection_program.ready_text.insert("end", "获取公钥挂载状况数据成功！")
                Connection_program.ready_text.config(state="disabled")

    # 获取用户公钥的具体对应的方法
    @staticmethod
    def get_hang_key():
        # 请求发送预处理
        choose_num = Connection_program.get_key_num.get()
        data_socket = Connection_program.login_socket
        num_list = len(Connection_program.hang_key_person_list)
        Connection_program.ready_text.config(state="normal")
        Connection_program.ready_text.delete("1.0", "end")
        if Connection_program.get_key_into_flag is True:
            if choose_num.isdigit():
                choose_num = int(choose_num)  # 格式转换
                if choose_num in range(1, num_list+1):
                    choose_name = Connection_program.hang_key_person_list[int(choose_num) - 1]
                    if choose_name in Crypto_program.other_get_key_name_list:
                        # print("\033[91m您已经获得过该用户的公钥了！\033[0m")
                        Connection_program.ready_text.insert("end", "你已经获得过该用户的公钥了！")
                    elif choose_name == Main_program.name:
                        # print("\033[91m您不能获取自己的公钥！\033[0m")
                        Connection_program.ready_text.insert("end", "您不能获得自己的公钥！")
                    else:
                        Connection_program.show_sever_key_get_text.config(state="normal")
                        # 向服务端发送请求获得用户数据的指令
                        data_socket.send("@sever_get_client_key".encode())
                        Connection_program.get_key_flag = False
                        time.sleep(0.1)  # 延迟，防止粘包
                        data_socket.send(choose_name.encode())  # 发送选择的用户名
                        next_flag = data_socket.recv(Connection_program.Max_data).decode()
                        if next_flag == "OK":
                            # 本次获取公钥，若成功则获取用户公钥按钮不再生效
                            Connection_program.get_key_num_button.config(state="disabled")
                            # print("获取公钥数据中...")
                            Connection_program.show_sever_key_get_text.insert("end", "获取公钥数据中\n")
                            other_sm2_public_key = data_socket.recv(Connection_program.Max_data).decode()
                            # print("对方SM2公钥为:{}".format(other_sm2_public_key))
                            Connection_program.show_sever_key_get_text.insert("end", "对方SM2公钥为:{}\n".format(other_sm2_public_key))
                            other_public_key = data_socket.recv(Connection_program.Max_data).decode()
                            # print("对方身份公钥为:{}".format(other_public_key))
                            Connection_program.show_sever_key_get_text.insert("end", "对方身份公钥为:{}\n".format(other_public_key))
                            other_share_public_key = data_socket.recv(Connection_program.Max_data).decode()
                            # print("对方预共享公钥为:{}".format(other_share_public_key))
                            Connection_program.show_sever_key_get_text.insert("end", "对方预共享公钥为:{}\n".format(other_share_public_key))
                            other_share_public_key_sign = data_socket.recv(Connection_program.Max_data).decode()
                            # print("对方预共享公钥签名为:{}".format(other_share_public_key_sign))
                            Connection_program.show_sever_key_get_text.insert("end", "对方预共享公钥签名为:{}\n".format(other_share_public_key_sign))
                            other_time_public_key = data_socket.recv(Connection_program.Max_data).decode()
                            # print("对方一次性公钥为：{}".format(other_time_public_key))
                            Connection_program.show_sever_key_get_text.insert("end", "对方一次性公钥为:{}\n".format(other_time_public_key))
                            # print("正在进行 X3DH 协议下的计算...")
                            Connection_program.show_sever_key_get_text.insert("end", "正在进行 X3DH 协议下的计算...\n")
                            # 调用 x3dh 的方法
                            ok_flag, connect_key, time_public_key = Crypto_program.x3dh_active_create(choose_name, other_sm2_public_key, other_public_key, other_share_public_key, other_share_public_key_sign, other_time_public_key)
                            if ok_flag is True:  # 判断计算结果
                                # print("计算获得的密钥为:{}".format(connect_key))
                                Connection_program.show_sever_key_get_text.insert("end", "计算获得的协商密钥为:{}\n".format(connect_key))
                                Connection_program.output_x3dh_key_text.delete("1.0", "end")
                                Connection_program.output_x3dh_key_text.insert("end", connect_key)
                                # print("使用的临时私钥对应的公钥为:{}".format(time_public_key))
                                Connection_program.show_sever_key_get_text.insert("end", "使用的临时私钥对应的公钥为:{}\n".format(time_public_key))
                                # 调用用户已获得公钥数据文件对计算结果进行保存
                                if File_program.update_client_get_key_list_file(1, Main_program.name, choose_name, other_time_public_key, connect_key, time_public_key):
                                    # print("计算结果及对应用户数据保存成功")
                                    Connection_program.show_sever_key_get_text.insert("end", "计算结果及对应用户数据保存成功！\n")
                                    Connection_program.ready_text.insert("end", "与用户 {} 的X3DH协商密钥计算成功！".format(choose_name))
                                else:
                                    # print("\033[91m计算结果及对应用户数据保存失败！\033[0m")
                                    Connection_program.show_sever_key_get_text.insert("end", "计算结果及对应用户数据保存失败！\n")
                            else:
                                # print("\033[91m计算失败\033[0m")
                                Connection_program.show_sever_key_get_text.insert("end", "计算失败\n")
                        else:
                            # print("\033[91m服务端数据异常\033[0m")
                            Connection_program.ready_text.insert("end", "服务端数据异常")
                else:
                    # print("\033[91m请输入正确的用户序号\033[0m")
                    Connection_program.ready_text.insert("end", "请输入正确的用户序号！")
            else:
                Connection_program.ready_text.insert("end", "请输入目标用户的序号！")
            Connection_program.show_sever_key_get_text.config(state="disabled")
            Connection_program.ready_text.config(state="disabled")
        else:
            Connection_program.ready_text.config(state="normal")
            Connection_program.ready_text.delete("1.0", "end")
            Connection_program.ready_text.insert("end", "您当前暂未请求获取公钥数据！")
            Connection_program.ready_text.config(state="disabled")

    # 展示用户已获得公钥数据的窗口  同时也是连接指定用户通信的窗口
    @staticmethod
    def show_client_key_window():
        # 初始设置相关参数
        Connection_program.show_client_key_connect_flag = False
        # 设置窗口参数
        Window_program.show_client_key_frame = tk.Frame(root_window, height=500, width=950, bd=3, padx=15, pady=10)
        Window_program.show_client_key_frame.place(anchor="center", relx=0.5, rely=0.5)
        # 窗口提示标签
        tk.Label(Window_program.show_client_key_frame, fg="blue", font=("黑体", 15), padx=10, pady=5, text="用户 {} 已获得公钥数据界面".format(Main_program.name)).grid(row=0, column=0, columnspan=3, padx=10, pady=10)
        # 数据展示文本框
        Connection_program.show_client_key_text = tk.Text(Window_program.show_client_key_frame, height=30, width=100, bd=3, font=("黑体", 10), fg="black", padx=10, pady=10)
        Connection_program.show_client_key_text.config(state="disabled")
        Connection_program.show_client_key_text.grid(row=1, column=0, columnspan=3, padx=10, pady=10)
        # 消息提示框
        Connection_program.ready_text = tk.Text(Window_program.show_client_key_frame, height=3, width=45, bd=3, font=("黑体", 15), fg="red", padx=10, pady=10)
        Connection_program.ready_text.config(state="disabled")
        Connection_program.ready_text.grid(row=2, column=0, columnspan=2, padx=10, pady=10)
        # 模式显示框
        Connection_program.show_client_key_mode_text = tk.Text(Window_program.show_client_key_frame, height=3, width=15, bd=3, font=("黑体", 15), fg="red", padx=10, pady=10)
        Connection_program.show_client_key_mode_text.insert("end", "数据显示模式")
        Connection_program.show_client_key_mode_text.config(state="disabled")
        Connection_program.show_client_key_mode_text.grid(row=2, column=2, padx=10, pady=10)
        # 数据输入框
        Connection_program.show_client_key_entry = tk.Entry(Window_program.show_client_key_frame, width=47, bd=3, font=("黑体", 15), fg="black", )
        Connection_program.show_client_key_entry.grid(row=3, column=0, columnspan=2, padx=10, pady=10)
        # 数据发送按钮
        Connection_program.show_client_key_input_button = tk.Button(Window_program.show_client_key_frame, padx=10, pady=10, font=("黑体", 15), text="发送", fg="green", command=Connection_program.show_client_key_send_function)
        Connection_program.show_client_key_input_button.config(state="disabled")
        Connection_program.show_client_key_input_button.grid(row=3, column=2, padx=10, pady=10)
        # 开启通信按钮
        Connection_program.show_client_key_connect_start_button = tk.Button(Window_program.show_client_key_frame, padx=10, pady=10, font=("黑体", 15), text="开启通信", fg="green", command=Connection_program.connect_target_client)
        Connection_program.show_client_key_connect_start_button.grid(row=4, column=0, padx=10, pady=10)
        # 结束通信按钮
        Connection_program.show_client_key_connect_close_button = tk.Button(Window_program.show_client_key_frame, padx=10, pady=10, font=("黑体", 15), text="结束通信", fg="red", command=Connection_program.show_client_key_connect_end_function)
        Connection_program.show_client_key_connect_close_button.config(state="disabled")
        Connection_program.show_client_key_connect_close_button.grid(row=4, column=1, padx=10, pady=10)
        # 退出按钮
        Connection_program.show_client_key_exit_button = tk.Button(Window_program.show_client_key_frame, padx=10, pady=10, font=("黑体", 15), text="退出", fg="red", command=Connection_program.show_client_key_window_to_interface_window)
        Connection_program.show_client_key_exit_button.grid(row=4, column=2, padx=10, pady=10)

        # 调用用户数据读取的方法
        Connection_program.browse_key()

    # 由公钥显示界面 转向 用户界面的方法
    @staticmethod
    def show_client_key_window_to_interface_window():
        if Connection_program.show_client_key_connect_flag is False:  # 判断当前是否处于通信状态
            Window_program.show_client_key_frame.destroy()
            Connection_program.interface_window()
        else:
            Connection_program.ready_text.config(state="normal")
            Connection_program.ready_text.delete("1.0", "end")
            Connection_program.ready_text.insert("end", "您当前处于通信状态，无法直接退出！")
            Connection_program.ready_text.config(state="disabled")

    # 定义用户查看当前已获得公钥数据的方法
    @staticmethod
    def browse_key():
        Connection_program.ready_text.config(state="normal")
        Connection_program.ready_text.delete("1.0", "end")
        Connection_program.show_client_key_text.config(state="normal")
        # print("正在读取用户数据中...")
        Connection_program.show_client_key_text.insert("end", "正在读取用户数据中...\n")
        if File_program.get_client_get_key_list_file(Main_program.name):
            # print("当前已获得的公钥数据如下:")
            Connection_program.show_client_key_text.insert("end", "当前已获得公钥数据如下:\n")
            data_num = len(Crypto_program.other_get_key_name_list)
            if data_num > 0:
                for i in range(0, data_num):
                    # print(i, "用户名:", Crypto_program.other_get_key_name_list[i])
                    Connection_program.show_client_key_text.insert("end", "{} 用户名: {}\n".format(i, Crypto_program.other_get_key_name_list[i]))
                    # print(i, "用户一次性公钥:", Crypto_program.other_get_time_key_list[i])
                    Connection_program.show_client_key_text.insert("end", "{} 用户一次性公钥: {}\n".format(i, Crypto_program.other_get_time_key_list[i]))
                    # print(i, "基于 X3DH 生成的密钥:", Crypto_program.other_get_x3dh_key_list[i])
                    Connection_program.show_client_key_text.insert("end", "{} 基于 X3DH 生成的协商密钥: {}\n".format(i, Crypto_program.other_get_x3dh_key_list[i]))
                    # print(i, "自己对应使用的一次性公钥:", Crypto_program.self_get_x3dh_time_key_list[i])
                    Connection_program.show_client_key_text.insert("end", "{} 自己使用的临时公钥: {}\n".format(i, Crypto_program.self_get_x3dh_time_key_list[i]))
                    Connection_program.show_client_key_text.insert("end", "\n---------------------------------\n\n")
                # print("请选择通信对象(输入对应序号，或者输入“退出”)")
                Connection_program.ready_text.insert("end", "若想联系目标用户，请输入对应序号后，点击下方“开启通信”按钮")
            else:
                Connection_program.show_client_key_text.insert("end", "哎呀，当前暂无已获得的公钥数据\n")
                # print("哎呀，当前暂无已获得的公钥数据")
        else:
            # print("\033[91m用户数据读取失败！\033[0m")
            Connection_program.ready_text.insert("end", "用户数据读取失败！")
        Connection_program.ready_text.config(state="disabled")
        Connection_program.show_client_key_text.config(state="disabled")
        Connection_program.show_client_key_input_button.config(state="normal")

    # 连接目标用户的与检测方法
    @staticmethod
    def connect_target_client():
        # 发送请求预处理
        Connection_program.show_client_key_connect_start_button.config(state="disabled")  # 截止本次通信完成，开启通信按钮失效
        choose_num = Connection_program.show_client_key_entry.get()
        Connection_program.ready_text.config(state="normal")
        Connection_program.ready_text.delete("1.0", "end")
        data_num = len(Crypto_program.other_get_key_name_list)
        if choose_num.isdigit():
            choose_num = int(choose_num)
            if choose_num in range(0, data_num):
                choose_name = Crypto_program.other_get_key_name_list[int(choose_num)]  # 选择的用户名
                choose_time_key = Crypto_program.other_get_time_key_list[int(choose_num)]  # 选择用户的 一次性公钥
                choose_x3dh_key = Crypto_program.other_get_x3dh_key_list[int(choose_num)]  # 基于该用户获得的X3DH密钥
                choose_self_time_key = Crypto_program.self_get_x3dh_time_key_list[int(choose_num)]  # 自己对应使用的一次性公钥
                # 调用客户端发起指定用户连接的方法
                Connection_program.client_x3dh_connect(choose_name, choose_time_key, choose_x3dh_key, choose_self_time_key)
            else:
                # print("\033[91m请输入正确的用户序号！\033[0m")
                Connection_program.ready_text.insert("end", "请输入正确的用户序号！")
                Connection_program.show_client_key_connect_start_button.config(state="normal")
        else:
            # print("\033[91m请输入正确的操作数据！\033[0m")
            Connection_program.ready_text.insert("end", "请输入正确的正确的操作数据！")
            Connection_program.show_client_key_connect_start_button.config(state="normal")
        Connection_program.ready_text.config(state="disabled")

    # 定义进行X3DH协议下通信的方法  (等同于等待模式 被动态)
    @staticmethod
    def client_x3dh_connect(other_name, other_time_public_key, x3dh_key, self_time_public_key):
        # 改变窗口内部分组件的参数
        Connection_program.show_client_key_text.config(state="normal")
        Connection_program.show_client_key_text.delete("1.0", "end")
        Connection_program.ready_text.config(state="normal")
        Connection_program.ready_text.delete("1.0", "end")
        Connection_program.show_client_key_connect_flag = True  # 改变通信状态
        # 开启通信
        data_socket = Connection_program.login_socket
        Connection_program.client_wait_mode_x3dh_key = x3dh_key
        # print("正在向服务端发送查询请求中...")
        Connection_program.show_client_key_text.insert("end", "正在向服务端发送查询请求中...\n")
        data_socket.send("@sever_connect_target_client".encode())  # 向服务器发送指定用户连接请求
        result_flag = data_socket.recv(Connection_program.Max_data).decode()
        if result_flag == "OK":  # 判断回复
            # print("服务端已接收请求，正在发送请求的用户名:{}".format(other_name))
            Connection_program.show_client_key_text.insert("end", "服务端已接收请求，正在发送请求的用户名:{}\n".format(other_name))
            data_socket.send(other_name.encode())
            result_flag = data_socket.recv(Connection_program.Max_data).decode()
            if result_flag == "OK":  # 判断目标用户是否出于等待模式
                # print("当前目标用户:{}，处于等待模式".format(other_name))
                Connection_program.show_client_key_text.insert("end", "当前目标用户:{}, 处于等待状态\n".format(other_name))
                # print("当前使用的对方用户一次性公钥为：{}".format(other_time_public_key))
                Connection_program.show_client_key_text.insert("end", "当前使用的对方的一次性公钥为:{}\n".format(other_time_public_key))
                # print("当前使用的X3DH密钥:{}".format(x3dh_key))
                Connection_program.show_client_key_text.insert("end", "当前使用的X3DH协商密钥为:{}\n".format(x3dh_key))
                # print("当前自己使用的临时公钥为:{}".format(self_time_public_key))
                Connection_program.show_client_key_text.insert("end", "当前自己使用的临时公钥为:{}\n".format(self_time_public_key))
                # print("正在等待目标用户回复中...")
                Connection_program.show_client_key_text.insert("end", "正在等待目标用户回复中...\n")
                flag = data_socket.recv(Connection_program.Max_data).decode()
                if flag == "OK":  # 判断对方用户回复结果
                    # 初始获得自己的公钥
                    File_program.get_client_all_key_data()
                    data_socket.send("OK".encode())
                    # print("用户 {} 同意了请求".format(other_name))
                    Connection_program.show_client_key_text.insert("end", "用户 {} 同意了通信请求\n".format(other_name))
                    # print("正在进行 X3DH 数据的发送")
                    Connection_program.show_client_key_text.insert("end", "正在进行 X3DH 所需数据的发送\n")
                    # 发送自己使用的对方的一次性公钥
                    data_socket.send(str(other_time_public_key).encode())
                    time.sleep(0.1)  # 时延，防止粘包
                    # print("已发送使用的对方的一次性公钥")
                    Connection_program.show_client_key_text.insert("end", "已发送使用的对方的一次性公钥\n")
                    # 发送自己的身份公钥
                    data_socket.send(str(Crypto_program.self_public_key).encode())
                    time.sleep(0.1)
                    # print("已发送自己的身份公钥")
                    Connection_program.show_client_key_text.insert("end", "已发送自己的公钥\n")
                    # 发送自己使用的临时公钥
                    data_socket.send(str(self_time_public_key).encode())
                    # print("已发送自己使用的临时公钥,正在等待对方计算完成...")
                    Connection_program.show_client_key_text.insert("end", "已发送自己使用的临时公钥，正在等待对方计算完成...\n")
                    # 接收对方完成计算的信号
                    ensure_data = data_socket.recv(Connection_program.Max_data).decode()
                    if ensure_data == "OK":
                        data_socket.send("OK".encode())
                        # print("对方已完成计算，正在进行验证...")
                        Connection_program.show_client_key_text.insert("end", "对方已完成计算，正在进行验证...\n")
                        # 生成验证消息
                        ensure_data = Crypto_program.random_key_born(20)  # 默认 20 位随机验证消息
                        # print("已生成随机验证消息:{}".format(ensure_data))
                        Connection_program.show_client_key_text.insert("end", "已生成随机验证消息:{}\n".format(ensure_data))
                        en_ensure_data = pysm4.encrypt_ecb(ensure_data, x3dh_key[0:15])
                        # print("使用 X3DH 密钥加密后为: {}".format(en_ensure_data))
                        Connection_program.show_client_key_text.insert("end", "使用 X3DH 密钥加密后为:{}\n".format(en_ensure_data))
                        data_socket.send(en_ensure_data.encode())
                        # print("已发送加密后的验证消息，等待对方的解密回复中...")
                        Connection_program.show_client_key_text.insert("end", "已发送加密后的验证消息，等待对方的解密回复中...\n")
                        # 接收对方的解密结果
                        other_data = data_socket.recv(Connection_program.Max_data).decode()
                        # print("已接收到对方解密结果:{}".format(other_data))
                        Connection_program.show_client_key_text.insert("end", "已接收到对方的解密结果:{}\n".format(other_data))
                        if other_data == ensure_data:
                            # print("对方验证通过")
                            Connection_program.show_client_key_text.insert("end", "对方验证通过\n")
                            data_socket.send("OK".encode())
                            # 改变通信连接状态
                            Connection_program.client_wait_mode_connect_flag = True
                            # 初始设置KDF，DH棘轮
                            File_program.init_x3dh_p_g()
                            Crypto_program.kdf_dh_self_time_private_key = Crypto_program.self_private_key  # 私钥设置为自己身份公钥的私钥
                            Crypto_program.kdf_chain_random_data = Connection_program.client_wait_mode_x3dh_key  # X3DH协商密钥为初始root key
                            kdf_dh_other_time_public_key = data_socket.recv(Connection_program.Max_data).decode()  # 接收对方初始的临时公钥
                            test_data = data_socket.recv(Connection_program.Max_data).decode()
                            Crypto_program.kdf_dh_other_new_time_public_key = kdf_dh_other_time_public_key
                            Crypto_program.kdf_dh_decry_function(test_data)
                            # 创建接收多线程
                            th = threading.Thread(target=Connection_program.create_wait_passive_accept, args=(data_socket, other_name,))
                            th.start()
                            Connection_program.ready_text.insert("end", "通信已就绪，可以开始发送消息！")
                            Connection_program.show_client_key_mode_text.config(state="normal")
                            Connection_program.show_client_key_mode_text.delete("1.0", "end")
                            Connection_program.show_client_key_mode_text.insert("end", "通信模式")
                            Connection_program.show_client_key_mode_text.config(state="disabled")
                            Connection_program.show_client_key_connect_close_button.config(state="normal")  # 结束通信按钮生效
                            Connection_program.show_client_key_exit_button.config(state="disabled")  # 退出按钮失效
                            """
                            while True:
                                talk_data = input()
                                if Connection_program.client_wait_mode_connect_flag is False:
                                    data_socket.send("@sever_wait_mode_passive_this_connect_end".encode())
                                    print(other_name, "您被中断通信，已结束本次通信")
                                    break
                                else:
                                    if talk_data == "exit" or talk_data == "退出" or talk_data == "@sever_wait_mode_this_connect_end":  # 判断是否主动中断通信
                                        data_socket.send("@sever_wait_mode_active_this_connect_end".encode())
                                        Connection_program.client_wait_mode_connect_flag = False
                                        break
                                    else:
                                        # 在此处加入双棘轮算法
                                        talk_data = Crypto_program.kdf_dh_encry_function(talk_data)
                                        data_socket.send(talk_data.encode())
                                        time.sleep(0.1)
                                        data_socket.send(str(Crypto_program.kdf_dh_self_time_public_key).encode())
                            """
                        else:
                            # print("\033[91m对方验证失败\033[0m")
                            Connection_program.show_client_key_text.insert("end", "对方验证失败！\n")
                            data_socket.send("NO".encode())
                            Connection_program.show_client_key_connect_flag = False
                    else:
                        data_socket.send("NO".encode())
                        # print("对方计算失败，已自动退出")
                        Connection_program.show_client_key_text.insert("end", "对方计算失败\n")
                        Connection_program.show_client_key_connect_flag = False
                else:
                    data_socket.send("NO".encode())
                    # print("用户 {} 拒绝了请求".format(other_name))
                    Connection_program.show_client_key_text.insert("end", "目标用户: {} 拒绝了通信请求!\n".format(other_name))
                    Connection_program.ready_text.insert("end", "目标用户: {} ,拒绝了通信请求!".format(other_name))
                    Connection_program.show_client_key_connect_flag = False
            else:
                # print("目标用户:{}，不处于等待状态".format(other_name))
                Connection_program.show_client_key_text.insert("end", "目标用户:{}, 不处于等待状态！\n".format(other_name))
                Connection_program.ready_text.insert("end", "目标用户:{}, 不处于等待状态！".format(other_name))
                Connection_program.show_client_key_connect_flag = False
        else:
            # print("\033[91m服务端拒绝了请求\033[0m")
            Connection_program.show_client_key_text.insert("end", "服务端拒绝了请求！\n")
            Connection_program.ready_text.insert("end", "服务端拒绝了请求！")
            Connection_program.show_client_key_connect_flag = False
        Connection_program.ready_text.config(state="disabled")

    # 定义发送消息的方法
    @staticmethod
    def show_client_key_send_function():
        if Connection_program.show_client_key_connect_flag is True:
            talk_data = Connection_program.show_client_key_entry.get()  # 获取发送的消息
            Connection_program.show_client_key_entry.delete(0, "end")  # 清空输入窗
            Connection_program.ready_text.config(state="normal")
            Connection_program.ready_text.delete("1.0", "end")
            if talk_data != "":
                data_socket = Connection_program.login_socket
                if talk_data == "exit" or talk_data == "退出" or talk_data == "@sever_wait_mode_active_this_connect_end":  # 判断是否主动中断通信
                    data_socket.send("@sever_wait_mode_active_this_connect_end".encode())
                    Connection_program.show_client_key_connect_flag = False
                    Connection_program.show_client_key_exit_button.config(state="normal")  # 退出按钮生效
                    Connection_program.ready_text.config(state="normal")
                    Connection_program.ready_text.delete("1.0", "end")
                    Connection_program.ready_text.insert("end", "您已结束会话，本次通信结束！")
                    Connection_program.ready_text.config(state="disabled")
                    Connection_program.show_client_key_input_button.config(state="disabled")  # 消息发送按钮失效
                    Connection_program.show_client_key_mode_text.config(state="normal")
                    Connection_program.show_client_key_mode_text.delete("1.0", "end")
                    Connection_program.show_client_key_mode_text.insert("1.0", "已结束通信")
                    Connection_program.show_client_key_mode_text.config(state="disabled")
                else:
                    Connection_program.show_client_key_text.insert("end", "{}: {}\n".format(Main_program.name, talk_data))  # 将发送的消息展示在界面上
                    # 在此处加入双棘轮算法
                    talk_data = Crypto_program.kdf_dh_encry_function(talk_data)
                    data_socket.send(talk_data.encode())
                    time.sleep(0.1)
                    data_socket.send(str(Crypto_program.kdf_dh_self_time_public_key).encode())
            else:
                Connection_program.ready_text.insert("发送的消息不能为空！")
            Connection_program.ready_text.config(state="disabled")

    # 结束通信按钮的方法
    @staticmethod
    def show_client_key_connect_end_function():
        if Connection_program.show_client_key_connect_flag is True:
            Connection_program.login_socket.send("@sever_wait_mode_active_this_connect_end".encode())
            Connection_program.show_client_key_connect_flag = False
            Connection_program.show_client_key_connect_close_button.config(state="disabled")  # 通信结束按钮失效
            Connection_program.show_client_key_input_button.config(state="normal")  # 消息发送按钮生效

    # 定义用户连接指定用户成功后启用的接收消息的多线程方法
    @staticmethod
    def create_wait_passive_accept(data_socket, other_name):
        while True:
            talk_data = data_socket.recv(Connection_program.Max_data).decode()
            if talk_data == "@client_wait_mode_passive_this_connect_end":
                Connection_program.show_client_key_connect_flag = False
                data_socket.send("@sever_wait_mode_passive_this_connect_end".encode())
                Connection_program.show_client_key_text.insert("end", "对方结束了会话，本次通信已结束\n")
                Connection_program.ready_text.config(state="normal")
                Connection_program.ready_text.delete("1.0", "end")
                Connection_program.ready_text.insert("end", "对方已结束会话，本次通信结束！")
                Connection_program.ready_text.config(state="disabled")
                break
            elif talk_data == "@client_wait_mode_active_this_connect_end":
                break
            else:
                # 此处加入双棘轮算法
                # print("接收到加密数据:{}".format(talk_data))
                Connection_program.show_client_key_text.insert("end", "接收到加密数据:{}\n".format(talk_data))
                key_data = data_socket.recv(Connection_program.Max_data).decode()
                Crypto_program.kdf_dh_other_new_time_public_key = key_data
                talk_data = Crypto_program.kdf_dh_decry_function(talk_data)
                Connection_program.show_client_key_text.insert("end", "\n")
                # print(other_name, ":", talk_data)
                Connection_program.show_client_key_text.insert("end", "{} : {}\n".format(other_name, talk_data))
            if Connection_program.show_client_key_connect_flag is False:
                break
        Connection_program.show_client_key_input_button.config(state="disabled")  # 消息发送按钮失效
        Connection_program.show_client_key_mode_text.config(state="normal")
        Connection_program.show_client_key_mode_text.delete("1.0", "end")
        Connection_program.show_client_key_mode_text.insert("1.0", "已结束通信")
        Connection_program.show_client_key_mode_text.config(state="disabled")
        Connection_program.show_client_key_connect_close_button.config(state="disabled")  # 结束通信按钮失效
        Connection_program.show_client_key_connect_start_button.config(state="normal")
        Connection_program.show_client_key_exit_button.config(state="normal")  # 退出按钮生效
        # print("接收消息线程已结束")
        Connection_program.show_client_key_text.insert("end", "接收消息线程已结束\n")

    # 聊天室模式 初始界面窗口
    @staticmethod
    def private_chat_room_mode_window():
        if Connection_program.private_room_mode_flag is True:  # 判断聊天室模式状态，防止重复发送请求指令
            flag = "OK"
        else:
            # 向服务端发送进入聊天室模式的指令
            Connection_program.login_socket.send("@sever_private_room_mode_join".encode())
            # 接收来自服务端的回复
            flag = Connection_program.login_socket.recv(Connection_program.Max_data).decode()
        if flag == "OK":  # 判断服务端返回结果
            Connection_program.private_room_mode_flag = True  # 改变标志量
            # 设置初始界面参数
            Window_program.private_chat_mode_frame = tk.Frame(root_window, height=500, width=800, bd=3, padx=15, pady=10, )
            Window_program.private_chat_mode_frame.place(anchor="center", relx=0.5, rely=0.5)
            # 消息提示窗口
            Connection_program.ready_text = tk.Text(Window_program.private_chat_mode_frame, height=3, width=45, bd=3, font=("黑体", 15), fg="red", padx=10, pady=10)
            Connection_program.ready_text.grid(padx=10, pady=10)
            Connection_program.ready_text.insert("end", "欢迎来到聊天室模式，{}".format(Main_program.name))
            Connection_program.ready_text.config(state="disabled")
            # 加入聊天室按钮
            tk.Button(Window_program.private_chat_mode_frame, padx=10, pady=10, font=("黑体", 15), text="加入聊天室", fg="blue", command=Connection_program.private_chat_room_window_to_guest).grid(padx=10, pady=10)
            # 创建聊天室按钮
            tk.Button(Window_program.private_chat_mode_frame, padx=10, pady=10, font=("黑体", 15), text="创建聊天室", fg="blue", command=Connection_program.private_chat_room_window_to_host).grid(padx=10, pady=10)
            # 退出按钮
            tk.Button(Window_program.private_chat_mode_frame, padx=10, pady=10, font=("黑体", 15), text="退出", fg="red", command=Connection_program.private_chat_room_window_to_interface_window).grid(padx=10, pady=10)

    # 由聊天室模式返回用户窗口的方法
    @staticmethod
    def private_chat_room_window_to_interface_window():
        if Connection_program.private_room_mode_flag is True:  # 判断当前客户端聊天室状态
            Connection_program.login_socket.send("@sever_private_room_mode_exit".encode())
            Connection_program.private_room_mode_flag = False
            Window_program.private_chat_mode_frame.destroy()
            Connection_program.interface_window()

    # 聊天室模式 窗口转换的方法
    @staticmethod
    def private_chat_room_window_to_host():
        Window_program.private_chat_mode_frame.destroy()
        Connection_program.private_chat_room_host_window()

    @staticmethod
    def private_chat_room_window_to_guest():
        Window_program.private_chat_mode_frame.destroy()
        Connection_program.private_chat_room_guest_window()

    # 聊天室模式 房主窗口
    @staticmethod
    def private_chat_room_host_window():
        # 初始设置参数
        Connection_program.private_chat_host_send_state = 1
        Connection_program.private_chat_room_password = "NONE"
        Connection_program.private_chat_room_member_num = 1
        Connection_program.private_chat_room_ready_flag = False
        # 设置窗口参数
        Window_program.private_chat_host_frame = tk.Frame(root_window, height=400, width=600, bd=3, padx=15, pady=10, )
        Window_program.private_chat_host_frame.place(anchor="center", relx=0.5, rely=0.5)
        # 窗口提示标签
        tk.Label(Window_program.private_chat_host_frame, fg="blue", font=("黑体", 15), padx=10, pady=5, text="用户 {} 的聊天室房主界面".format(Main_program.name)).grid(row=0, column=0, columnspan=3, padx=10, pady=10)
        # 聊天数据框
        Connection_program.private_chat_text = tk.Text(Window_program.private_chat_host_frame, height=30, width=50, bd=3, padx=15, pady=10, font=("黑体", 10))
        Connection_program.private_chat_text.insert("end", "请输入房间最大容纳人数(2-10)\n")
        Connection_program.private_chat_text.grid(row=1, column=0, columnspan=2, padx=10, pady=10)
        # 成员列表
        Connection_program.private_chat_member_text = tk.Text(Window_program.private_chat_host_frame, height=20, width=10, bd=3, padx=15, pady=10, font=("黑体", 15), fg="red")
        Connection_program.private_chat_member_text.insert("end", "成员列表\n")
        Connection_program.private_chat_member_text.config(state="disabled")
        Connection_program.private_chat_member_text.grid(row=1, column=2, padx=10, pady=10)
        # 消息提示框
        Connection_program.ready_text = tk.Text(Window_program.private_chat_host_frame, height=2, width=50, bd=3, padx=15, pady=10, font=("黑体", 15), fg="red")
        Connection_program.ready_text.insert("end", "请先设置房间参数，再创建房间")
        Connection_program.ready_text.config(state="disabled")
        Connection_program.ready_text.grid(row=2, column=0, columnspan=3, padx=10, pady=10)
        # 消息输入框
        Connection_program.private_chat_entry = tk.Entry(Window_program.private_chat_host_frame, width=38, bd=3, font=("黑体", 15), )
        Connection_program.private_chat_entry.grid(row=3, column=0, columnspan=2, padx=10, pady=10)
        # 消息发送按钮
        Connection_program.private_chat_send_button = tk.Button(Window_program.private_chat_host_frame, padx=10, pady=10, font=("黑体", 15), text="发送", fg="green", command=Connection_program.private_chat_host_send_function)
        Connection_program.private_chat_send_button.grid(row=3, column=2, padx=10, pady=10)
        # 创建房间的按钮
        Connection_program.private_chat_connect_start_button = tk.Button(Window_program.private_chat_host_frame, padx=10, pady=10, font=("黑体", 15), text="创建房间", fg="green", command=Connection_program.client_create_private_room_function)
        # Connection_program.private_chat_connect_start_button.config(state="disabled")
        Connection_program.private_chat_connect_start_button.grid(row=4, column=0, padx=10, pady=10)
        # 撤销房间的按钮
        Connection_program.private_chat_connect_close_button = tk.Button(Window_program.private_chat_host_frame, padx=10, pady=10, font=("黑体", 15), text="撤销房间", fg="red", command=Connection_program.private_chat_host_connect_close_function)
        Connection_program.private_chat_connect_close_button.config(state="disabled")
        Connection_program.private_chat_connect_close_button.grid(row=4, column=1, padx=10, pady=10)
        # 退出按钮
        Connection_program.private_chat_exit_button = tk.Button(Window_program.private_chat_host_frame, padx=10, pady=10, font=("黑体", 15), text="退出", fg="red", command=Connection_program.private_chat_host_window_to_mode_window)
        Connection_program.private_chat_exit_button.grid(row=4, column=2, padx=10, pady=10)

    # 聊天室模式 房主窗口退出的方法
    @staticmethod
    def private_chat_host_window_to_mode_window():
        Window_program.private_chat_host_frame.destroy()
        Connection_program.private_chat_room_mode_window()

    # 聊天室模式 房主消息发送按钮对应的方法
    @staticmethod
    def private_chat_host_send_function():
        talk_data = Connection_program.private_chat_entry.get()
        Connection_program.private_chat_entry.delete(0, "end")  # 清空输入框数据
        Connection_program.ready_text.config(state="normal")
        Connection_program.ready_text.delete("1.0", "end")
        if Connection_program.private_chat_host_send_state == 1:  # 人数输入
            if talk_data.isdigit():  # 判断输入是否合法
                if 2 <= int(talk_data) <= 10:
                    Connection_program.private_chat_room_member_num = int(talk_data)
                    Connection_program.private_chat_text.insert("end", "您设置的房间最大容纳人数为:{}\n".format(talk_data))
                    Connection_program.private_chat_text.insert("end", "请输入房间口令(默认“NONE”为无口令)\n")
                    Connection_program.ready_text.insert("end", "请输入房间口令(默认“NONE”为无口令)")
                    Connection_program.private_chat_host_send_state = 2
                else:
                    Connection_program.ready_text.insert("end", "请输入 2 - 10 之间人数的数字！")
            else:
                Connection_program.ready_text.insert("end", "请输入数字！")
        elif Connection_program.private_chat_host_send_state == 2:
            if talk_data != "":
                Connection_program.private_chat_room_password = talk_data
                Connection_program.private_chat_text.insert("end", "您设置的房间口令为:{}\n".format(talk_data))
                Connection_program.private_chat_send_button.config(state="disabled")  # 发送按钮失效
                Connection_program.ready_text.insert("end", "房间参数设置完毕，可以创建房间！")
                Connection_program.private_chat_room_ready_flag = True
            else:
                Connection_program.ready_text.insert("end", "房间口令输入不能为空！")
        elif Connection_program.private_chat_host_send_state == 3:
            if talk_data != "@sever_private_room_exit":
                if talk_data != "":
                    Connection_program.login_socket.send((Main_program.name + ":" + talk_data).encode())
                else:
                    Connection_program.ready_text.insert("end", "输入不可为空！")
            else:
                Connection_program.ready_text.insert("end", "非法输入！")
        Connection_program.ready_text.config(state="disabled")

    # 聊天室模式 房主撤销房间的方法
    @staticmethod
    def private_chat_host_connect_close_function():
        if Connection_program.private_chat_host_send_state == 3:
            Connection_program.login_socket.send("@sever_private_room_exit".encode())  # 发送撤销房间的消息
            Connection_program.private_chat_connect_close_button.config(state="disabled")  # 撤销房间的按钮失效
            Connection_program.private_chat_send_button.config(state="disabled")  # 消息发送按钮失效
            Connection_program.private_chat_text.insert("end", "您撤销了房间！")
            Connection_program.private_chat_host_send_state = 0

    # 聊天室模式  更新房间的成员的方法
    @staticmethod
    def private_chat_update_member_text(mode, name):  # mode： 1 添加， 2 移除
        if mode == 1:
            Connection_program.private_chat_member_list.append(name)
            Connection_program.private_chat_room_member_num += 1
        else:
            if name in Connection_program.private_chat_member_list:
                Connection_program.private_chat_member_list.remove(name)
                Connection_program.private_chat_room_member_num -= 1
        Connection_program.private_chat_member_text.config(state="normal")
        Connection_program.private_chat_member_text.delete("1.0", "end")
        for item in Connection_program.private_chat_member_list:
            Connection_program.private_chat_member_text.insert("end", item)
            Connection_program.private_chat_member_text.insert("end", "\n")

    """
    # 弃稿
    # 定义客户端用户向服务端查询及创建聊天室房间的方法  聊天室模式界面
    @staticmethod
    def client_create_connect_room(data_socket):
        if Connection_program.private_room_mode_flag is True:  # 判断聊天室模式状态，防止重复发送请求指令
            flag = "OK"
        else:
            # 向服务端发送进入聊天室模式的指令
            data_socket.send("@sever_private_room_mode_join".encode())
            # 接收来自服务端的回复
            flag = data_socket.recv(Connection_program.Max_data).decode()
        if flag == "OK":
            Connection_program.private_room_mode_flag = True  # 改变聊天室模式状态
            print("欢迎来到聊天室模式:{}".format(Main_program.name))
            while True:
                print("1 查询以及加入聊天室")
                print("2 创建聊天室房间")
                print("3 退出聊天室模式")
                change_flag = input("请选择操作:")
                if change_flag in ["1", "2", "3"]:
                    break
                else:
                    print("\033[91m请选择正确的操作序号！\033[0m")
            if change_flag == "1":
                # 调用查询当前聊天室的方法
                Connection_program.client_query_private_join_room_function()
            elif change_flag == "2":
                # 调用创建聊天室的方法
                Connection_program.client_create_private_room_function()
            else:
                print("正在退出聊天室模式")
                # 向服务端发送退出聊天室模式的方法
                data_socket.send("@sever_private_room_mode_exit".encode())
                Connection_program.private_room_mode_flag = False
        else:
            print("\033[91m进入聊天室模式失败！\033[0m")
        Connection_program.private_room_mode_flag = False
        # 调用返回用户界面的方法
        Connection_program.interface_main(data_socket)
     
    """

    # 定义创建个人聊天室的方法  房主方法
    @staticmethod
    def client_create_private_room_function():
        # 改变相关组件参数
        Connection_program.ready_text.config(state="normal")
        Connection_program.ready_text.delete("1.0", "end")
        if Connection_program.private_chat_room_ready_flag is True:
            Connection_program.private_chat_connect_start_button.config(state="disabled")  # 创建房间的按钮失效
            Connection_program.private_chat_exit_button.config(state="disabled")  # 退出按钮失效
            Connection_program.private_chat_text.config(state="normal")
            # 向服务端发起创建请求
            data_socket = Connection_program.login_socket
            data_socket.send("@sever_private_room_create".encode())  # 向服务端发送请求创建个人聊天室的方法
            Connection_program.private_chat_text.insert("end", "已向服务端发送创建房间的请求！\n")
            flag = data_socket.recv(Connection_program.Max_data).decode()  # 接受服务端的回复
            if flag == "OK":  # 判断客户端回复结果
                Connection_program.private_chat_text.insert("end", "请求成功！正在发送房间参数\n")
                Connection_program.login_socket.send(str(Connection_program.private_chat_room_member_num).encode())  # 发送房间的最大容纳人数
                time.sleep(0.1)  # 时延防止粘包
                Connection_program.login_socket.send(str(Connection_program.private_chat_room_password).encode())  # 发送房间的口令
                # 接收返回消息
                flag = data_socket.recv(Connection_program.Max_data).decode()
                if flag == "OK":
                    Connection_program.private_room_talk_flag = True  # 改变聊天室工作状态
                    # 创建接收消息多线程
                    recv_data_th = threading.Thread(target=Connection_program.private_room_recv_data_function, args=(data_socket,))
                    recv_data_th.start()  # 启用多线程
                    # print("房间创建成功")
                    Connection_program.ready_text.delete("1.0", "end")
                    Connection_program.ready_text.insert("end", "房间创建成功！")
                    Connection_program.private_chat_text.insert("end", "您的房间已创建！\n")
                    Connection_program.private_chat_host_send_state = 3  # 改变消息发送按钮状态
                    Connection_program.private_chat_send_button.config(state="normal")  # 消息发送按钮生效
                    Connection_program.private_chat_connect_close_button.config(state="normal")  # 撤销房间的按钮生效
                else:
                    # print("\033[91m房间创建失败\033[0m")
                    Connection_program.ready_text.delete("1.0", "end")
                    Connection_program.ready_text.insert("end", "房间创建失败！")
                    Connection_program.private_chat_text.insert("end", "房间创建失败！")
                    Connection_program.private_chat_exit_button.config(state="normal")  # 退出按钮生效
                    Connection_program.private_chat_connect_start_button.config(state="normal")  # 创建房间的按钮生效
                    Connection_program.private_chat_host_send_state = 1
                    Connection_program.private_chat_room_ready_flag = False
            else:
                # print("\033[91m请求失败\033[0m")
                Connection_program.ready_text.insert("end", "请求创建房间失败！")
                Connection_program.private_chat_text.config(state="disabled")
                Connection_program.private_chat_exit_button.config(state="normal")  # 退出按钮生效
        else:
            Connection_program.ready_text.insert("end", "请先设置房间参数！")
        Connection_program.ready_text.config(state="disabled")

    # 聊天室模式 成员窗口
    @staticmethod
    def private_chat_room_guest_window():
        # 初始设置参数
        Connection_program.private_chat_guest_send_state = 0
        Connection_program.private_chat_room_ready_flag = False
        # 设置窗口参数
        Window_program.private_chat_guest_frame = tk.Frame(root_window, height=400, width=600, bd=3, padx=15, pady=10, )
        Window_program.private_chat_guest_frame.place(anchor="center", relx=0.5, rely=0.5)
        # 窗口提示标签
        tk.Label(Window_program.private_chat_guest_frame, fg="blue", font=("黑体", 15), padx=10, pady=5, text="用户 {} 的聊天室成员界面".format(Main_program.name)).grid(row=0, column=0, columnspan=3, padx=10, pady=10)
        # 聊天数据框
        Connection_program.private_chat_text = tk.Text(Window_program.private_chat_guest_frame, height=30, width=70, bd=3, padx=15, pady=10, font=("黑体", 10), )
        Connection_program.private_chat_text.insert("end", "请先查询房间状况\n")
        Connection_program.private_chat_text.config(state="disabled")
        Connection_program.private_chat_text.grid(row=1, column=0, columnspan=3, padx=10, pady=10)
        # 消息提示框
        Connection_program.ready_text = tk.Text(Window_program.private_chat_guest_frame, height=2, width=50, bd=3, padx=15, pady=10, font=("黑体", 15), fg="red", )
        Connection_program.ready_text.insert("end", "等待加入房间")
        Connection_program.ready_text.config(state="disabled")
        Connection_program.ready_text.grid(row=2, column=0, columnspan=3, padx=10, pady=10)
        # 消息输入框
        Connection_program.private_chat_entry = tk.Entry(Window_program.private_chat_guest_frame, width=38, bd=3, font=("黑体", 15), )
        Connection_program.private_chat_entry.grid(row=3, column=0, columnspan=2, padx=10, pady=10)
        # 消息发送按钮
        Connection_program.private_chat_send_button = tk.Button(Window_program.private_chat_guest_frame, padx=10, pady=10, font=("黑体", 15), text="发送", fg="green", command=Connection_program.private_chat_room_guest_send_function)
        Connection_program.private_chat_send_button.config(state="disabled")
        Connection_program.private_chat_send_button.grid(row=3, column=2, padx=10, pady=10)
        # 开启通信按钮
        Connection_program.private_chat_connect_start_button = tk.Button(Window_program.private_chat_guest_frame, padx=10, pady=10, font=("黑体", 15), text="查询房间", fg="green", command=Connection_program.client_query_private_join_room_function)
        Connection_program.private_chat_connect_start_button.grid(row=4, column=0, padx=10, pady=10)
        # 结束通信按钮
        Connection_program.private_chat_connect_close_button = tk.Button(Window_program.private_chat_guest_frame, padx=10, pady=10, font=("黑体", 15), text="退出房间", fg="red", command=Connection_program.private_chat_room_guest_connect_close_function)
        Connection_program.private_chat_connect_close_button.config(state="disabled")
        Connection_program.private_chat_connect_close_button.grid(row=4, column=1, padx=10, pady=10)
        # 退出按钮
        Connection_program.private_chat_exit_button = tk.Button(Window_program.private_chat_guest_frame, padx=10, pady=10, font=("黑体", 15), text="退出", fg="red", command=Connection_program.private_chat_guest_window_to_mode_widow)
        Connection_program.private_chat_exit_button.grid(row=4, column=2, padx=10, pady=10)

    # 聊天室模式  成员窗口退出的方法
    @staticmethod
    def private_chat_guest_window_to_mode_widow():
        Window_program.private_chat_guest_frame.destroy()
        Connection_program.private_chat_room_mode_window()

    # 用户查询聊天室及加入的方法  房间的成员方法
    @staticmethod
    def client_query_private_join_room_function():
        # 改变组件参数
        Connection_program.private_chat_connect_start_button.config(state="disabled")  # 查询房间的按钮失效
        Connection_program.private_chat_exit_button.config(state="disabled")  # 退出按钮失效
        Connection_program.private_chat_text.config(state="normal")
        # 发送请求查询当前房间的状况
        data_socket = Connection_program.login_socket
        next_flag = False
        target_room_name = ""
        target_room_encry_state = ""
        # print("正在请求中...")
        Connection_program.private_chat_text.insert("end", "正在请求中...\n")
        Connection_program.private_room_host_name_list = []  # 房主名列表
        Connection_program.private_room_now_person_num_list = []  # 房间现人数列表
        Connection_program.private_room_max_person_num_list = []  # 房间最大容纳人数列表
        Connection_program.private_room_encry_list = []  # 房间加密状态列表
        # 向服务端发送聊天室查询请求
        data_socket.send("@sever_private_room_query".encode())
        flag = data_socket.recv(Connection_program.Max_data).decode()
        if flag == "OK":  # 判断返回结果
            # print("正在获得及处理数据中...")
            Connection_program.private_chat_text.insert("end", "正在获得及处理数据中...\n")
            while True:
                name_data = data_socket.recv(Connection_program.Max_data).decode()  # 接收房主名
                if name_data != "@all_data_end":  # 判断数据接收结束标志
                    Connection_program.private_room_host_name_list.append(name_data)
                    now_person_num = data_socket.recv(Connection_program.Max_data).decode()  # 接收现人数
                    Connection_program.private_room_now_person_num_list.append(now_person_num)
                    max_person_num = data_socket.recv(Connection_program.Max_data).decode()  # 接收最大人数
                    Connection_program.private_room_max_person_num_list.append(max_person_num)
                    encry_state = data_socket.recv(Connection_program.Max_data).decode()  # 接收加密状态
                    Connection_program.private_room_encry_list.append(encry_state)
                else:
                    break
            if len(Connection_program.private_room_host_name_list) != 0:
                # print("当前存在的聊天室房间如下")
                Connection_program.private_chat_text.insert("end", "当前存在的聊天室房间如下:\n")
                room_num = int(len(Connection_program.private_room_host_name_list))
                for i in range(0, room_num):
                    # print("{} 房主名:{},人数:{}/{},加密状态:{}".format(i, private_room_name_list[i], private_room_now_person_num_list[i], private_room_max_person_num_list[i], private_room_encry_list[i]))
                    Connection_program.private_chat_text.insert("end", "{} 房主名:{},人数:{}/{},加密状态:{}\n".format(i, Connection_program.private_room_host_name_list[i], Connection_program.private_room_now_person_num_list[i], Connection_program.private_room_max_person_num_list[i], Connection_program.private_room_encry_list[i]))
                Connection_program.private_chat_guest_send_state = 1
                Connection_program.private_chat_room_ready_flag = True
                Connection_program.private_chat_send_button.config(state="normal")  # 消息发送按钮生效
                Connection_program.ready_text.config(state="normal")
                Connection_program.ready_text.delete("1.0", "end")
                Connection_program.ready_text.insert("end", "请输入对应房间序号以加入对应房间，或输入“退出”不加入房间")
                Connection_program.ready_text.config(state="disabled")
            else:
                # print("当前暂无聊天室")
                Connection_program.private_chat_text.insert("end", "当前暂无聊天室！\n")
                data_socket.send("@sever_private_room_not_join".encode())
                Connection_program.private_chat_exit_button.config(state="normal")  # 退出按钮生效
        else:
            # print("\033[91m查询失败！\033[0m")
            Connection_program.private_chat_text.insert("end", "查询失败！\n")

    # 聊天室模式 成员发送消息按钮对应的方法
    @staticmethod
    def private_chat_room_guest_send_function():
        talk_data = Connection_program.private_chat_entry.get()
        Connection_program.private_chat_entry.delete(0, "end")
        Connection_program.ready_text.config(state="normal")
        Connection_program.ready_text.delete("1.0", "end")
        if Connection_program.private_chat_room_ready_flag is True:  # 判断是否查询了房间的状况
            if Connection_program.private_chat_guest_send_state == 1:  # 判断此时的状态
                room_num = len(Connection_program.private_room_host_name_list)  # 获得房间的数量
                if talk_data.isdigit():
                    talk_data = int(talk_data)
                    if talk_data in range(0, room_num):
                        if int(Connection_program.private_room_max_person_num_list[talk_data]) - int(Connection_program.private_room_now_person_num_list[talk_data]) > 0:  # 判断目标房间是否还有多余的空间
                            target_room_name = Connection_program.private_room_host_name_list[talk_data]
                            Connection_program.login_socket.send("@sever_private_room_join_target".encode())  # 向服务端发送加入房间的请求
                            time.sleep(0.1)  # 时延防止粘包
                            Connection_program.login_socket.send(target_room_name.encode())  # 发送房主名
                            if Connection_program.private_room_encry_list[talk_data] == "NO":  # 判断目标房间是否处于加密状态
                                Connection_program.login_socket.send("NONE".encode())
                                flag = Connection_program.login_socket.recv(Connection_program.Max_data).decode()
                                if flag == "OK":  # 判断是否加入了目标用户房间
                                    Connection_program.ready_text.insert("end", "加入目标用户房间成功！")
                                    Connection_program.private_chat_guest_send_state = 3  # 改变按键状态
                                    Connection_program.private_chat_connect_close_button.config(state="normal")  # 结束通信按钮生效
                                    # 启用接收消息的多线程
                                    recv_th = threading.Thread(target=Connection_program.private_room_recv_data_function, args=(Connection_program.login_socket, ))
                                    recv_th.start()
                                else:
                                    Connection_program.ready_text.insert("end", "加入目标用户房间失败！")
                                    Connection_program.private_chat_guest_send_state = 1  # 改变发送按钮状态
                                    Connection_program.private_chat_exit_button.config(state="normal")  # 退出按钮生效
                                    Connection_program.private_chat_exit_button.config(state="disabled")  # 消息发送按钮失效
                            else:
                                Connection_program.ready_text.insert("end", "请输入该房间的口令")
                                Connection_program.private_chat_guest_send_state = 2
                        else:
                            # print("您选择的房间已满，请重新选择，或输入“退出”")
                            Connection_program.ready_text.insert("end", "您选择的房间已满，请重新选择，或输入“退出”")
                    else:
                        Connection_program.ready_text.insert("end", "请输入已有的房间序号！")
                elif talk_data == "退出":
                    Connection_program.ready_text.insert("end", "您选择了不加入聊天室！")
                    Connection_program.login_socket.send("@sever_private_room_not_join".encode())  # 向服务端发送中断加入聊天室的通知
                    Connection_program.private_chat_send_button.config(state="disabled")  # 消息发送按钮失效
                    Connection_program.private_chat_exit_button.config(state="normal")  # 退出按钮生效
                else:
                    # print("\033[91m请输入正确的房间序号\033[0m")
                    Connection_program.ready_text.insert("end", "请输入正确的房间序号！")
            elif Connection_program.private_chat_guest_send_state == 2:  # 房间的口令输入
                Connection_program.login_socket.send(talk_data.encode())  # 发送用户输入的口令
                flag = Connection_program.login_socket.recv(Connection_program.Max_data).decode()
                if flag == "OK":  # 判断房间加入结果
                    Connection_program.ready_text.insert("end", "加入房间成功！")
                    Connection_program.private_chat_guest_send_state = 3
                    Connection_program.private_chat_connect_close_button.config(state="normal")  # 退出房间的按钮生效
                    # 启用接收消息的多线程
                    recv_th = threading.Thread(target=Connection_program.private_room_recv_data_function, args=(Connection_program.login_socket,))
                    recv_th.start()
                else:
                    Connection_program.ready_text.insert("end", "加入房间失败！")
                    Connection_program.private_chat_guest_send_state = 0
                    Connection_program.private_chat_send_button.config(state="disabled")  # 消息发送按钮失效
                    Connection_program.private_chat_exit_button.config(state="normal")  # 退出按钮生效
            elif Connection_program.private_chat_guest_send_state == 3:  # 正常通信
                if talk_data != "" and talk_data != "输入的消息不能为空！":
                    talk_data = Main_program.name + ":" + talk_data
                    Connection_program.login_socket.send(talk_data.encode())
                else:
                    Connection_program.ready_text.insert("end", "输入的消息不能为空！")
        else:
            Connection_program.ready_text.insert("end", "请先查询房间状态！")
        Connection_program.ready_text.config(state="disabled")

    # 聊天室模式 成员退出房间的方法
    @staticmethod
    def private_chat_room_guest_connect_close_function():
        if Connection_program.private_chat_guest_send_state == 3:  # 判断发送按钮此时的状态
            Connection_program.login_socket.send("@sever_private_room_active_exit".encode())  # 向服务端发送退出房间提示
            Connection_program.private_chat_send_button.config(state="disabled")  # 消息发送按钮失效
            Connection_program.private_chat_connect_close_button.config(state="disabled")  # 退出房间的按钮失效
            Connection_program.private_chat_exit_button.config(state="normal")  # 退出按钮生效
            Connection_program.private_chat_guest_send_state = 1


    # 定义客户端 聊天室模式 接收消息的多线程
    @staticmethod
    def private_room_recv_data_function(data_socket):
        Connection_program.private_chat_text.insert("end", "您已进入房间\n")
        while True:
            talk_data = data_socket.recv(Connection_program.Max_data).decode()
            if talk_data != "@client_private_room_exit":
                if talk_data != "@client_private_room_destroy":
                    if "@client_private_chat_mode_append_member:" in talk_data:
                        Connection_program.private_chat_update_member_text(1, talk_data[40:])
                    elif "@client_private_chat_mode_remove_member:" in talk_data:
                        Connection_program.private_chat_update_member_text(2, talk_data[40:])
                    else:
                        # print(talk_data)
                        talk_data = talk_data + "\n"
                        Connection_program.private_chat_text.insert("end", talk_data)
                else:
                    # print("房主关闭了房间")
                    Connection_program.ready_text.config(state="normal")
                    Connection_program.ready_text.delete("1.0", "end")
                    Connection_program.ready_text.insert("end", "房主撤销了房间！")
                    Connection_program.ready_text.config(state="disabled")
                    if len(Connection_program.private_room_host_name_list) != 0:  # 通过判断该列表是否为0，来判断该接收线程的所属是房主还是成员
                        Connection_program.login_socket.send("@sever_private_room_passive_exit".encode())  # 返回服务端对应的用户线程
                    break
            else:
                Connection_program.ready_text.config(state="normal")
                Connection_program.ready_text.delete("1.0", "end")
                Connection_program.ready_text.insert("end", "您已退出了房间！")
                Connection_program.ready_text.config(state="disabled")
                break
        Connection_program.private_chat_send_button.config(state="disabled")  # 消息发送按钮失效
        Connection_program.private_chat_connect_close_button.config(state="disabled")  # 结束通信按钮失效
        Connection_program.private_chat_exit_button.config(state="normal")  # 退出按钮生效
        Connection_program.private_room_talk_flag = False
        Connection_program.private_chat_guest_send_state = 1
        Connection_program.private_chat_host_send_state = 1
        Connection_program.private_chat_room_ready_flag = False
        # print("已退出聊天室")
        Connection_program.private_chat_text.insert("end", "已退出聊天室！\n")

    # 等待模式数据显示窗口
    @staticmethod
    def wait_mode_window():
        # 设置初始变量
        Connection_program.wait_mode_alive_flag = False
        Connection_program.wait_mode_connect_flag = False
        Connection_program.wait_mode_connect_state = 0  # 初始设置为未连接到用户状态
        # 设置窗口参数
        Window_program.wait_mode_frame = tk.Frame(root_window, height=500, width=950, bd=3, padx=15, pady=10)
        Window_program.wait_mode_frame.place(anchor="center", relx=0.5, rely=0.5)
        # 窗口提示标签
        tk.Label(Window_program.wait_mode_frame, fg="blue", font=("黑体", 15), padx=10, pady=5, text="用户 {} 的等待模式界面".format(Main_program.name)).grid(row=0, column=0, columnspan=4, padx=10, pady=10)
        # 数据展示文本框
        Connection_program.wait_mode_text = tk.Text(Window_program.wait_mode_frame, height=30, width=95, bd=3, font=("黑体", 10), fg="black", padx=10, pady=10)
        Connection_program.wait_mode_text.config(state="disabled")
        Connection_program.wait_mode_text.grid(row=1, column=0, columnspan=4, padx=10, pady=10)
        # 消息提示框
        Connection_program.ready_text = tk.Text(Window_program.wait_mode_frame, height=3, width=40, bd=3, font=("黑体", 15), fg="red", padx=10, pady=10)
        Connection_program.ready_text.config(state="disabled")
        Connection_program.ready_text.grid(row=2, column=0, columnspan=3, padx=10, pady=10)
        # 通信状态显示框
        Connection_program.wait_mode_state_text = tk.Text(Window_program.wait_mode_frame, height=3, width=20, bd=3, font=("黑体", 15), fg="red", padx=10, pady=10)
        Connection_program.wait_mode_state_text.insert("end", "等待进入等待模式")
        Connection_program.wait_mode_state_text.config(state="disabled")
        Connection_program.wait_mode_state_text.grid(row=2, column=3, padx=10, pady=10)
        # 数据输入
        Connection_program.wait_mode_entry = tk.Entry(Window_program.wait_mode_frame, width=42, bd=3, font=("黑体", 15), fg="black", )
        Connection_program.wait_mode_entry.grid(row=3, column=0, columnspan=3, padx=10, pady=10)
        # 数据发送按钮
        Connection_program.wait_mode_send_button = tk.Button(Window_program.wait_mode_frame, padx=10, pady=10, font=("黑体", 15), text="发送", fg="green", command=Connection_program.wait_mode_send_data_function)
        Connection_program.wait_mode_send_button.config(state="disabled")
        Connection_program.wait_mode_send_button.grid(row=3, column=3, padx=10, pady=10)
        # 进入等待按钮
        Connection_program.wait_mode_connect_start_button = tk.Button(Window_program.wait_mode_frame, padx=10, pady=10, font=("黑体", 15), text="进入等待", fg="green", command=Connection_program.client_join_wait_mode)
        Connection_program.wait_mode_connect_start_button.grid(row=4, column=0, padx=10, pady=10)
        # 结束本次通信按钮
        Connection_program.wait_mode_connect_next_button = tk.Button(Window_program.wait_mode_frame, padx=10, pady=10, font=("黑体", 15), text="结束通信", fg="red", command=Connection_program.wait_mode_connect_next_function)
        Connection_program.wait_mode_connect_next_button.config(state="disabled")
        Connection_program.wait_mode_connect_next_button.grid(row=4, column=1, padx=10, pady=10)
        # 结束等待模式按钮
        Connection_program.wait_mode_connect_close_button = tk.Button(Window_program.wait_mode_frame, padx=10, pady=10, font=("黑体", 15), text="退出等待", fg="red", command=Connection_program.wait_mode_exit_function)
        Connection_program.wait_mode_connect_close_button.config(state="disabled")
        Connection_program.wait_mode_connect_close_button.grid(row=4, column=2, padx=10, pady=10)
        # 退出按钮
        Connection_program.wait_mode_exit_button = tk.Button(Window_program.wait_mode_frame, padx=10, pady=10, font=("黑体", 15), text="退出", fg="red", command=Connection_program.wait_mode_window_to_interface_window)
        Connection_program.wait_mode_exit_button.grid(row=4, column=3, padx=10, pady=10)

    # 由等待模式窗口 转向 用户窗口的方法
    @staticmethod
    def wait_mode_window_to_interface_window():
        if Connection_program.wait_mode_alive_flag is False:  # 判断当前等待模式是否处于激活状态
            Window_program.wait_mode_frame.destroy()
            Connection_program.interface_window()
        else:
            Connection_program.ready_text.config(state="normal")
            Connection_program.ready_text.delete("1.0", "end")
            Connection_program.ready_text.insert("end", "您当前处于通信状态，无法直接退出！")
            Connection_program.ready_text.config(state="disabled")

    # 定义客户端用户进入等待模式的方法  (等待模式 主动态)
    @staticmethod
    def client_join_wait_mode():
        # 改变相关组件参数设置
        Connection_program.wait_mode_exit_button.config(state="disabled")  # 截止本次通信连接完成，退出按钮失效
        Connection_program.wait_mode_connect_start_button.config(state="disabled")  # 截止本次通信结束，进入等待按钮失效
        Connection_program.wait_mode_text.config(state="normal")
        Connection_program.ready_text.config(state="normal")
        Connection_program.ready_text.delete("1.0", "end")
        # 通信连接
        data_socket = Connection_program.login_socket
        # print("正在请求中...")
        Connection_program.wait_mode_text.insert("end", "正在请求中...\n")
        data_socket.send("@sever_wait_mode_join".encode())
        flag = data_socket.recv(Connection_program.Max_data).decode()  # 接收服务端回复结果
        if flag == "OK":  # 判断回复结果
            # print("已成功进入等待模式")
            Connection_program.ready_text.insert("end", "进入等待模式成功！")
            Connection_program.wait_mode_text.insert("end", "进入等待模式成功！\n")
            Connection_program.client_wait_mode_flag = True
            # 创建等待线程并开启
            th = threading.Thread(target=Connection_program.create_wait_active_accept, args=(data_socket, ))
            th.start()
            # 改变相关组件的参数
            Connection_program.wait_mode_connect_close_button.config(state="normal")  # 退出等待按钮生效
            Connection_program.wait_mode_state_text.config(state="normal")
            Connection_program.wait_mode_state_text.delete("1.0", "end")
            Connection_program.wait_mode_state_text.insert("end", "当前正处于等待模式")
            Connection_program.wait_mode_state_text.config(state="disabled")
        else:
            # print("\033[91m进入等待模式失败！\033[0m")
            Connection_program.ready_text.insert("end", "进入等待模式失败！")
            Connection_program.wait_mode_connect_start_button.config(state="normal")  # 进入等待按钮生效
            Connection_program.wait_mode_exit_button.config(state="normal")  # 退出等待模式按钮生效
        Connection_program.ready_text.config(state="disabled")
        Connection_program.wait_mode_text.config(state="disabled")

    # 等待模式 主动态 消息发送按钮的方法
    @staticmethod
    def wait_mode_send_data_function():
        if Connection_program.client_wait_mode_flag is True:  # 判断当前等待模式状态
            if Connection_program.client_wait_mode_connect_flag is True:  # 判断当前通信是否连接到了其他用户
                data_socket = Connection_program.login_socket
                talk_data = Connection_program.wait_mode_entry.get()  # 获取用户输入的数据
                Connection_program.wait_mode_entry.delete(0, "end")  # 清空输入数据
                if Connection_program.wait_mode_connect_state == 1:  # 判断是否连接到了其他用户
                    if str(talk_data) == "1":  # 判断是否进行 X3DH 协议下的通信验证连接
                        # 通知对方用户请求结果
                        data_socket.send("OK".encode())
                        # 开始进行 X3DH 协议下的验证连接
                        # print("正在进行 X3DH 协议下的验证...")
                        Connection_program.wait_mode_text.insert("end", "正在进行 X3DH 协议下的验证...\n")
                    else:
                        data_socket.send("NO".encode())
                        Connection_program.wait_mode_text.insert("end", "您拒绝了与用户: {} 的通信连接！\n".format(Connection_program.client_wait_mode_other_name))
                    Connection_program.wait_mode_send_button.config(state="disabled")  # 改变发送按钮状态
                elif Connection_program.wait_mode_connect_state == 2:
                    # 进行正常的通信会话
                    # 此处加入双棘轮算法
                    Connection_program.wait_mode_text.insert("end", "{}: {}\n".format(Main_program.name, talk_data))  # 将发送的消息显示到屏幕上
                    talk_data = Crypto_program.kdf_dh_encry_function(talk_data)
                    data_socket.send(talk_data.encode())
                    time.sleep(0.1)
                    data_socket.send(str(Crypto_program.kdf_dh_self_time_public_key).encode())
                else:
                    Connection_program.ready_text.config(state="normal")
                    Connection_program.ready_text.delete("1.0", "end")
                    Connection_program.ready_text.insert("end", "数据判断异常！")
                    Connection_program.ready_text.config(state="disabled")

    # 等待模式 主动态 退出等待的按钮的方法
    @staticmethod
    def wait_mode_exit_function():
        if Connection_program.client_wait_mode_flag is True:  # 判断等待模式激活状态
            if Connection_program.client_wait_mode_connect_flag is False:
                Connection_program.client_wait_mode_flag = False  # 更改状态
                Connection_program.login_socket.send("@sever_wait_mode_exit".encode())  # 向服务端发送退出等待模式的方法
                Connection_program.wait_mode_connect_close_button.config(state="disabled")  # 退出等待按钮失效
                Connection_program.wait_mode_connect_start_button.config(state="normal")  # 进入等待按钮生效
                Connection_program.wait_mode_exit_button.config(state="disabled")  # 退出等待模式按钮失效
            else:
                Connection_program.ready_text.config(state="normal")
                Connection_program.ready_text.delete("1.0", "end")
                Connection_program.ready_text.insert("end", "您当前正处于通信状态，请先退出通信状态！")
                Connection_program.ready_text.config(state="disabled")

    # 等待模式 主动态 结束通信按钮的方法
    @staticmethod
    def wait_mode_connect_next_function():
        if Connection_program.client_wait_mode_flag is True:  # 判断等待模式激活状态
            if Connection_program.client_wait_mode_connect_flag is True:  # 判断通信连接状态
                Connection_program.client_wait_mode_connect_flag = False  # 更改通信状态
                Connection_program.login_socket.send("@sever_wait_mode_active_this_connect_end".encode())
                Connection_program.wait_mode_connect_next_button.config(state="disabled")  # 结束通信按钮失效
                Connection_program.wait_mode_send_button.config(state="disabled")  # 消息发送按钮失效
                Connection_program.wait_mode_connect_close_button.config(state="normal")  # 退出等待模式按钮生效
                Connection_program.ready_text.config(state="normal")
                Connection_program.ready_text.delete("1.0", "end")
                Connection_program.ready_text.insert("end", "你已主动结束了与用户:{} 的通信!".format(Connection_program.client_wait_mode_other_name))
                Connection_program.ready_text.config(state="disabled")

    # 定义 等待模式 主动态 用户的接收线程
    @staticmethod
    def create_wait_active_accept(data_socket):
        # 预处理相关组件参数设置
        Connection_program.wait_mode_text.config(state="normal")  # 改变数据展示框状态
        # print("等待模式接收线程已启用")
        Connection_program.wait_mode_text.insert("end", "等待模式接收线程已启用！\n")
        while True:
            talk_data = data_socket.recv(Connection_program.Max_data).decode()
            Connection_program.client_wait_mode_connect_flag = True
            if talk_data != "@client_wait_mode_exit":  # 判断是否结束线程
                other_name = talk_data  # 接收对方用户名
                Connection_program.ready_text.config(state="normal")
                Connection_program.ready_text.delete("1.0", "end")
                # print("用户 {} 请求与您建立通信，若同意请输入“1”:".format(other_name))
                Connection_program.ready_text.insert("end", "用户: {},请求与您建立通信，若同意请输入“1".format(other_name))
                Connection_program.ready_text.config(state="disabled")
                Connection_program.wait_mode_send_button.config(state="normal")  # 消息发送按钮生效
                Connection_program.wait_mode_connect_state = 1  # 改变通信状态
                Connection_program.client_wait_mode_other_name = other_name
                talk_data = data_socket.recv(Connection_program.Max_data).decode()  # 接收服务端的判断结果
                if talk_data == "OK":  # 判断是否进行 X3DH 验证
                    # 改变相关组件的参数设置
                    Connection_program.wait_mode_send_button.config(state="disabled")  # 截止 X3DH 协商密钥计算完成，消息发送按钮失效
                    Connection_program.ready_text.config(state="normal")
                    Connection_program.ready_text.delete("1.0", "end")
                    Connection_program.ready_text.insert("end", "您同意了与用户:{} 的通信连接请求！".format(other_name))
                    Connection_program.ready_text.config(state="disabled")
                    # 开始进行 X3DH 协议下的通信连接
                    # 接收使用的我方一次性公钥
                    self_time_public_key = data_socket.recv(Connection_program.Max_data).decode()
                    # print("接收到对方使用的我方的一次性公钥: {}".format(self_time_public_key))
                    Connection_program.wait_mode_text.insert("end", "接收到对方使用的我方的一次性公钥:{}\n".format(self_time_public_key))
                    # 接收对方身份公钥
                    other_public_key = data_socket.recv(Connection_program.Max_data).decode()
                    # print("接收到对方的身份公钥为: {}".format(other_public_key))
                    Connection_program.wait_mode_text.insert("end", "接收到对方的身份公钥为:{}\n".format(other_public_key))
                    # 接收对方临时公钥
                    other_time_public_key = data_socket.recv(Connection_program.Max_data).decode()
                    # print("接收到对方使用的临时公钥: {}".format(other_time_public_key))
                    Connection_program.wait_mode_text.insert("end", "接收到对方使用的临时公钥:{}\n".format(other_time_public_key))
                    # 调用 X3DH 密钥生成的算法
                    flag, Connection_program.client_wait_mode_x3dh_key = Crypto_program.x3dh_passive_create(self_time_public_key, other_name, other_public_key, other_time_public_key)
                    if flag is True:  # 判断计算结果
                        # print("计算成功！")
                        Connection_program.wait_mode_text.insert("end", "计算成功！\n")
                        # 向对方发送计算完成通知
                        data_socket.send("OK".encode())
                        # print("计算获得的密钥为：{}".format(Connection_program.client_wait_mode_x3dh_key))
                        Connection_program.wait_mode_text.insert("end", "计算获得的密钥为:{}\n".format(Connection_program.client_wait_mode_x3dh_key))
                        # 进行密钥验证
                        # print("正在进行密钥验证...")
                        Connection_program.wait_mode_text.insert("end", "正在进行密钥验证...\n")
                        # 接收对方发送的验证消息
                        ensure_data = data_socket.recv(Connection_program.Max_data).decode()
                        # print("已接收到对方发送的验证消息为:{}".format(ensure_data))
                        Connection_program.wait_mode_text.insert("end", "已接收到对方发送的验证消息为:{}\n".format(ensure_data))
                        # 解密
                        clear_data = pysm4.decrypt_ecb(ensure_data, Connection_program.client_wait_mode_x3dh_key[0:15])
                        # print("解密验证消息后的明文为:{}".format(clear_data))
                        Connection_program.wait_mode_text.insert("end", "解密验证后明文为:{}\n".format(clear_data))
                        # 发送解密后的验证消息
                        data_socket.send(clear_data.encode())
                        # print("已发送解密后的验证消息，正在等待对方验证中...")
                        Connection_program.wait_mode_text.insert("end", "已发送解密后的验证消息，正在等待对方验证中...\n")
                        # 接收对方的回复结果
                        result_data = data_socket.recv(Connection_program.Max_data).decode()
                        if result_data == "OK":  # 判断对方的回复
                            # print("验证通过")
                            Connection_program.wait_mode_text.insert("end", "验证通过！\n")
                            data_socket.send("OK".encode())  # 通知服务端验证结果
                            Connection_program.wait_mode_send_button.config(state="normal")  # 消息发送按钮生效
                            Connection_program.wait_mode_connect_next_button.config(state="normal")  # 结束通信按钮生效
                            Connection_program.wait_mode_connect_state = 2  # 改变用户通信状态变量
                            Connection_program.client_wait_mode_connect_flag = True
                            # 初始化设置KDF，DH棘轮
                            File_program.init_x3dh_p_g()
                            Crypto_program.kdf_dh_other_new_time_public_key = other_public_key  # 对方身份公钥为 salt 输入
                            Crypto_program.kdf_chain_random_data = Connection_program.client_wait_mode_x3dh_key  # X3DH密钥为初始root key
                            test_data = Crypto_program.kdf_dh_encry_function("init")
                            data_socket.send(str(Crypto_program.kdf_dh_self_time_public_key).encode())  # 发送自己的临时公钥
                            time.sleep(0.1)
                            data_socket.send(test_data.encode())
                            # 改变组件相关参数
                            Connection_program.wait_mode_state_text.config(state="normal")
                            Connection_program.wait_mode_state_text.delete("1.0", "end")
                            Connection_program.wait_mode_state_text.insert("end", "当前处于通信状态")
                            Connection_program.wait_mode_state_text.config(state="disabled")
                            Connection_program.wait_mode_connect_close_button.config(state="disabled")
                            while True:  # 正常的加密通信阶段
                                talk_data = data_socket.recv(Connection_program.Max_data).decode()
                                if talk_data == "@client_wait_mode_active_this_connect_end":  # 判断通信是否为主动结束与对方的通信
                                    break
                                elif talk_data == "@client_wait_mode_passive_this_connect_end":   # 判断是否为对方结束通信
                                    data_socket.send("@sever_wait_mode_passive_this_connect_end".encode())  # 通知服务端本次通信结束
                                    Connection_program.ready_text.config(state="normal")
                                    Connection_program.ready_text.delete("1.0", "end")
                                    Connection_program.ready_text.insert("end", "对方已结束会话，本次通信结束，已返回等待模式")
                                    Connection_program.ready_text.config(state="disabled")
                                    break
                                else:
                                    # 此处加入双棘轮算法
                                    key_data = data_socket.recv(Connection_program.Max_data).decode()
                                    Crypto_program.kdf_dh_other_new_time_public_key = key_data
                                    talk_data = Crypto_program.kdf_dh_decry_function(talk_data)
                                    # print(other_name, ":", talk_data)
                                    Connection_program.wait_mode_text.insert("end", "{} : {}\n".format(other_name, talk_data))
                            # 改变容器内相应组件的参数设置
                            Connection_program.wait_mode_connect_next_button.config(state="disabled")  # 结束通信按钮失效
                            Connection_program.wait_mode_send_button.config(state="disabled")  # 消息发送按钮失效
                            Connection_program.wait_mode_connect_close_button.config(state="normal")  # 退出等待按钮生效
                            Connection_program.wait_mode_connect_state = 0  # 改变用户通信状态变量
                            Connection_program.client_wait_mode_connect_flag = False
                            # 改变状态显示
                            Connection_program.wait_mode_state_text.config(state="normal")
                            Connection_program.wait_mode_state_text.delete("1.0", "end")
                            Connection_program.wait_mode_state_text.insert("end", "当前处于等待模式")
                            Connection_program.wait_mode_state_text.config(state="disabled")
                        else:
                            data_socket.send("NO".encode())
                            # print("\033[91m验证失败\033[0m")
                            Connection_program.wait_mode_text.insert("end", "验证失败！\n")
                            Connection_program.client_wait_mode_connect_flag = False
                    else:
                        data_socket.send("NO".encode())
                        # print("\033[91m计算失败\033[0m")
                        Connection_program.wait_mode_text.insert("end", "计算失败！\n")
                        Connection_program.client_wait_mode_connect_flag = False
                else:
                    Connection_program.wait_mode_text.insert("end", "本次通信已结束!\n")
                    Connection_program.wait_mode_connect_state = 0
                    Connection_program.client_wait_mode_connect_flag = False
            else:
                Connection_program.wait_mode_send_button.config(state="disabled")  # 消息发送按钮失效
                Connection_program.wait_mode_connect_next_button.config(state="disabled")  # 结束通信按钮失效
                Connection_program.wait_mode_connect_start_button.config(state="normal")  # 进入等待模式按钮生效
                Connection_program.wait_mode_connect_close_button.config(state="normal")  # 结束等待模式按钮生效
                Connection_program.ready_text.config(state="normal")
                Connection_program.ready_text.delete("1.0", "end")
                Connection_program.ready_text.insert("end", "已退出等待模式")
                Connection_program.ready_text.config(state="disabled")
                Connection_program.wait_mode_state_text.config(state="normal")
                Connection_program.wait_mode_state_text.delete("1.0", "end")
                Connection_program.wait_mode_state_text.insert("end", "等待进入等待模式")
                Connection_program.wait_mode_state_text.config(state="disabled")
                break
        Connection_program.client_wait_mode_connect_flag = False
        Connection_program.client_wait_mode_flag = False
        # print("等待模式接收线程已结束")
        Connection_program.wait_mode_exit_button.config(state="normal")  # 退出按钮生效
        Connection_program.wait_mode_text.insert("end", "等待模式接收线程已结束！\n")

    # 注册界面
    @staticmethod
    def register_window():
        # 以下为界面参数
        # 初始化所需要的参数变量
        Connection_program.register_name = tk.StringVar()
        Connection_program.register_password_one = tk.StringVar()
        Connection_program.register_password_two = tk.StringVar()
        # 设置窗口参数
        Window_program.register_frame = tk.Frame(root_window, height=500, width=600, bd=3)
        Window_program.register_frame.place(anchor="center", relx=0.5, rely=0.5)
        # 就绪文本框
        Connection_program.ready_text = tk.Text(Window_program.register_frame, font=("黑体", 18), fg="red", height=1, width=40, padx=10, pady=5)
        Connection_program.ready_text.config(state="disabled")
        Connection_program.ready_text.grid(row=0, columnspan=2, padx=10, pady=10)

        # 提示语
        tk.Label(Window_program.register_frame, text="请输入数据以注册", font=("kaiti", 18), padx=10, pady=10).grid(row=1, columnspan=2, padx=10, pady=10)
        # 用户名
        tk.Label(Window_program.register_frame, text="账户名:", font=("黑体", 15), padx=10, pady=10).grid(row=2, column=0, padx=10, pady=10)
        tk.Entry(Window_program.register_frame, textvariable=Connection_program.register_name, font=("黑体", 13), width=23).grid(row=2, column=1, padx=10, pady=10)
        # 密码及确认
        tk.Label(Window_program.register_frame, text="密码:", font=("黑体", 15), padx=10, pady=10).grid(row=3, column=0, padx=10, pady=10)
        tk.Entry(Window_program.register_frame, textvariable=Connection_program.register_password_one, font=("黑体", 13), width=23).grid(row=3, column=1, padx=10, pady=10)
        tk.Label(Window_program.register_frame, text="确认密码:", font=("黑体", 15), padx=10, pady=10).grid(row=4, column=0, padx=10, pady=10)
        tk.Entry(Window_program.register_frame, textvariable=Connection_program.register_password_two, font=("黑体", 13), width=23).grid(row=4, column=1, padx=10, pady=10)
        # 注册
        Connection_program.register_button = (tk.Button(Window_program.register_frame, text="注册", font=("黑体", 15), relief="raised", fg="green", padx=5, pady=5, command=Connection_program.start_register_connect))
        Connection_program.register_button.grid(row=5, column=0, padx=10, pady=10)
        # 取消
        tk.Button(Window_program.register_frame, text="取消", font=("黑体", 15), relief="raised", fg="red", padx=5, pady=5, command=Connection_program.register_window_to_start_window).grid(row=5, column=1, padx=10, pady=10)

    # 开启通信的方法  注册模式
    @staticmethod
    def start_register_connect():
        end_flag = False
        next_flag = False
        # 请求发送预处理
        name = Connection_program.register_name.get()
        password_one = Connection_program.register_password_one.get()
        password_two = Connection_program.register_password_two.get()
        if name == "" or name == "用户名不能为空！":
            Connection_program.register_name.set("用户名不能为空！")
        else:
            if password_one == "" or password_one == "密码不能为空！":
                Connection_program.register_password_one.set("密码不能为空！")
            else:
                if Crypto_program.test_key_strong(password_one, 16):
                    if password_one != password_two:
                        Connection_program.register_password_two.set("密码不一致！")
                    else:
                        next_flag = True
                        Connection_program.register_button.config(state="disabled")  # 截止本次通信完成前，该按钮不再生效
                else:
                    Connection_program.register_password_one.set("密钥不合法或强度不够！")
        if next_flag is True:
            # 一旦启动，改变通信状态
            Connection_program.connect_flag = True
            # 通信部分
            IP = Connection_program.get_host_ip()  # 获得本机的IPV4地址
            PORT = Connection_program.PORT  # 设置端口号
            # 设置网络层协议，传输层协议
            data_socket = socket(AF_INET, SOCK_STREAM)  # IP协议，TCP
            # 尝试进行连接
            try:
                data_socket.connect((IP, PORT))
                # 接收随机验证消息
                random_data = data_socket.recv(Connection_program.Max_data).decode()
                # 发送验证消息
                sign_hash_data = SystemSign.system_sign_message(random_data)
                data_socket.send(sign_hash_data.encode())
                # print("正在尝试连接服务器...")
                Connection_program.ready_text.config(state="normal")
                Connection_program.ready_text.insert("end", "正在尝试连接服务器...")
                Connection_program.ready_text.config(state="disabled")
                # 接收验证结果
                result_data = data_socket.recv(Connection_program.Max_data).decode()
                if result_data == "OK":
                    # print("连接服务器成功")
                    Connection_program.ready_text.config(state="normal")
                    Connection_program.ready_text.delete("1.0", "end")
                    Connection_program.ready_text.insert("end", "连接服务器成功！正在发送注册请求中...")
                    Connection_program.ready_text.config(state="normal")
                    data_socket.send("@sever_connect_mode2".encode())  # 客户端向服务端发送请求用户注册指令
                    ok_flag = data_socket.recv(Connection_program.Max_data).decode()  # 客户端接收来自服务端的返回确认
                    if ok_flag == "OK":  # 判断返回结果
                        # 发送注册用户名
                        data_socket.send(name.encode())
                        # 接收服务端查询结果
                        flag = data_socket.recv(Connection_program.Max_data).decode()
                        Connection_program.ready_text.config(state="normal")
                        Connection_program.ready_text.delete("1.0", "end")
                        if flag == "OK":
                            hash_password = sm3.sm3_hash(func.bytes_to_list(password_two.encode()))  # 获得用户密码的哈希值
                            data_socket.send(hash_password.encode())  # 发送该哈希值至服务端
                            # 接收服务端接收结果
                            ok_flag = data_socket.recv(Connection_program.Max_data).decode()
                            # 调用用户已获得公钥数据文件生成的方法
                            ok_flg2 = File_program.create_client_get_key_list_file(name)
                            if ok_flag == "OK" and ok_flg2 is True:  # 判断复合返回结果
                                # print("注册成功")
                                Connection_program.ready_text.insert("end", "注册成功！")
                                end_flag = True
                            else:
                                # print("\033[91m 注册失败！\033[0m")
                                Connection_program.ready_text.insert("end", "注册失败！")
                        else:
                            # print("\033[91m 已存在相同用户名！\033[0m")
                            Connection_program.ready_text.insert("end", "已存在相同用户名！")
                            data_socket.send("@sever_client_create_exit".encode())  # 发送终止用户注册指令
                        Connection_program.ready_text.config(state="disabled")
                    else:
                        # print("\033[91m请求失败\033[0m")
                        Connection_program.ready_text.config(state="normal")
                        Connection_program.ready_text.delete("1.0", "end")
                        Connection_program.ready_text.insert("end", "请求失败！")
                        Connection_program.ready_text.config(state="disabled")
                else:
                    # print("\033[91连接服务器失败\033[0m")
                    Connection_program.ready_text.config(state="normal")
                    Connection_program.ready_text.delete("1.0", "end")
                    Connection_program.ready_text.insert("end", "连接服务器失败！")
                    Connection_program.ready_text.config(state="disabled")
            except ConnectionRefusedError:  # 检测连接状况
                Connection_program.ready_text.config(state="normal")
                Connection_program.ready_text.delete("1.0", "end")
                Connection_program.ready_text.insert("end", "服务器不在工作状态或维护中!")
                Connection_program.ready_text.config(state="disabled")
                Connection_program.register_button.config(state="normal")
            finally:
                # 关闭连接
                data_socket.close()
                Main_program.clear_screen()  # 清屏
                if end_flag is False:
                    Connection_program.register_button.config(state="normal")

    # 定义从注册界面返回初始界面的方法
    @staticmethod
    def register_window_to_start_window():
        Window_program.register_frame.destroy()
        Main_program.start_application()

    # 定义发送消息端的多线程的方法   弃用
    @staticmethod
    def send_data(data_socket):
        print("发送端线程已启用")
        while True:
            if Connection_program.connect_flag is False:
                data_socket.close()
                break
            # 等待用户输入发送消息
            data = input()
            if data == "结束" or data == "exit":
                data_socket.send("@client_connect_end".encode())
                Connection_program.connect_flag = False
                break
            else:
                data = Main_program.name + ":" + data
                data_socket.send(data.encode())
                # print("已发送消息{}".format(data))
        print("发送端线程已结束")

    # 定义接收消息端的多线程的方法   弃用
    @staticmethod
    def recv_data(data_socket):
        print("接收端线程已启用")
        while True:
            if Connection_program.connect_flag is False:
                data_socket.close()
                break
            data = data_socket.recv(Connection_program.Max_data).decode()
            print(data)
            if data == "结束" or data == "exit":
                Connection_program.connect_flag = False
                break
        print("接收端线程已结束")


# 创建客户端文件处理类
class File_program(object):
    def __init__(self):
        super().__init__()

    client_get_key_list_file_name_part = "(3.50)get_key_list_file.txt"

    # 定义创建用户公私钥对文件的方法
    @staticmethod
    def create_client_key_file():
        name = Main_program.name
        client_key_file_name = "client(3.50)" + str(name) + ".txt"  # 组合成用户目标文件
        if os.path.exists(client_key_file_name):  # 判断用户公私钥对数据文件是否存在
            pass
        else:
            client_key_file = open(client_key_file_name, "w+")  # 创建并打开目标用户文件
            client_key_file.write(str(Crypto_program.self_sm2_public_key) + "\n")  # 用户的SM2公钥
            client_key_file.write("@file_should_division\n")
            client_key_file.write(str(Crypto_program.self_sm2_private_key) + "\n")  # 用户的SM2私钥
            client_key_file.write("@file_should_division\n")
            client_key_file.write(str(Crypto_program.self_public_key) + "\n")  # 用户的身份公钥
            client_key_file.write("@file_should_division\n")
            client_key_file.write(str(Crypto_program.self_private_key) + "\n")  # 用户身份公钥对应的私钥
            client_key_file.write("@file_should_division\n")
            client_key_file.write(str(Crypto_program.self_share_public_key) + "\n")  # 用户的预共享公钥
            client_key_file.write("@file_should_division\n")
            client_key_file.write(str(Crypto_program.self_share_private_key) + "\n")  # 用户的预共享公钥对应的私钥
            client_key_file.write("@file_should_division\n")
            client_key_file.write(str(Crypto_program.self_share_public_key_sign) + "\n")  # 写入用户预共享公钥的签名
            client_key_file.write("@file_should_division\n")
            for key_item in Crypto_program.self_time_key_list:  # 遍历用户一次性公私钥对列表，将数据写入目标文件中
                client_key_file.write(str(key_item) + "\n")
                client_key_file.write("@file_should_division\n")
            client_key_file.close()  # 关闭用户目标文件

    # 定义从用户公私钥对文件中获取用户公私钥对数据的方法
    @staticmethod
    def get_client_all_key_data():
        # 初始化用户一次性公私钥对数据
        Crypto_program.self_time_key_list.clear()
        client_key_file_name = "client(3.50)" + str(Main_program.name) + ".txt"  # 组合成用户目标文件
        if os.path.exists(client_key_file_name):  # 判断当前用户文件是否存在
            client_key_file = open(client_key_file_name, "r")  # 以只读模式打开用户文件
            client_key_data_list = client_key_file.readlines()
            client_key_file.close()
            division_num = 1
            time_data = ''   # 用于存储暂时数据
            for client_data in client_key_data_list:
                if client_data.strip("\n") != "@file_should_division":
                    time_data += client_data
                else:
                    if division_num == 1:  # 用户SM2公私钥对
                        Crypto_program.self_sm2_public_key = time_data[0:len(time_data) - 1]
                    elif division_num == 2:
                        Crypto_program.self_sm2_private_key = time_data[0:len(time_data) - 1]
                    elif division_num == 3:  # 用户身份身份私钥对
                        Crypto_program.self_public_key = time_data[0:len(time_data) - 1]
                    elif division_num == 4:
                        Crypto_program.self_private_key = time_data[0:len(time_data) - 1]
                    elif division_num == 5:  # 用户预共享公私钥对
                        Crypto_program.self_share_public_key = time_data[0:len(time_data) - 1]
                    elif division_num == 6:
                        Crypto_program.self_share_private_key = time_data[0:len(time_data) - 1]
                    elif division_num == 7:  # 用户预共享公钥的SM2签名
                        Crypto_program.self_share_public_key_sign = time_data[0:len(time_data) - 1]
                    else:  # 用户的一次性公私钥对
                        Crypto_program.self_time_key_list.append(time_data[0:len(time_data) - 1])
                    time_data = ""  # 临时数据变量重置
                    division_num += 1  # 分割标志数加 1
            return True  # 返回获取结果
        else:
            return False

    # 定义修改用户公私钥对数据文件中一次性公私钥对的方法
    @staticmethod
    def update_client_all_data(time_public_key, time_private_key):
        client_key_file_name = "client(3.50)" + str(Main_program.name) + ".txt"  # 组合成用户目标文件
        # 将该一次性公私钥对从对应的列表中移除
        Crypto_program.self_time_key_list.remove(time_public_key)
        Crypto_program.self_time_key_list.remove(time_private_key)
        if os.path.exists(client_key_file_name):  # 判断用户公私钥对数据文件是否存在
            return False
        else:
            client_key_file = open(client_key_file_name, "w+")  # 以覆盖写的方式打开用户公私钥对的数据文件
            client_key_file.write(str(Crypto_program.self_sm2_public_key) + "\n")  # 用户的SM2公钥
            client_key_file.write("@file_should_division\n")
            client_key_file.write(str(Crypto_program.self_sm2_private_key) + "\n")  # 用户的SM2私钥
            client_key_file.write("@file_should_division\n")
            client_key_file.write(str(Crypto_program.self_public_key) + "\n")  # 用户的身份公钥
            client_key_file.write("@file_should_division\n")
            client_key_file.write(str(Crypto_program.self_private_key) + "\n")  # 用户身份公钥对应的私钥
            client_key_file.write("@file_should_division\n")
            client_key_file.write(str(Crypto_program.self_share_public_key) + "\n")  # 用户的预共享公钥
            client_key_file.write("@file_should_division\n")
            client_key_file.write(str(Crypto_program.self_share_private_key) + "\n")  # 用户的预共享公钥对应的私钥
            client_key_file.write("@file_should_division\n")
            client_key_file.write(str(Crypto_program.self_share_public_key_sign) + "\n")  # 写入用户预共享公钥的签名
            client_key_file.write("@file_should_division\n")
            for key_item in Crypto_program.self_time_key_list:  # 遍历用户一次性公私钥对列表，将数据写入目标文件中
                client_key_file.write(str(key_item) + "\n")
                client_key_file.write("@file_should_division\n")
            client_key_file.close()  # 关闭用户目标文件
            return True

    # 定义初始化获得 p, g 的方法
    @staticmethod
    def init_x3dh_p_g():
        p_file = open("Value_P.txt", "r")  # 打开目标文件
        Crypto_program.x3dh_p = int(p_file.read())  # 获取对应数据，并且将数据的格式转换
        p_file.close()
        g_file = open("Value_G.txt", "r")
        Crypto_program.x3dh_g = int(g_file.read())
        g_file.close()
        q_file = open("Value_Q.txt", "r")
        Crypto_program.x3dh_q = int(q_file.read())
        q_file.close()

    # 定义创建用户已获得公钥数据文件的方法
    @staticmethod
    def create_client_get_key_list_file(self_name):
        client_file_name = str(self_name) + File_program.client_get_key_list_file_name_part
        if os.path.exists(client_file_name):  # 检测该文件是否存在
            return False  # 返回创建结果
        else:  # 创建用户获得的公钥数据文件
            client_file = open(client_file_name, "a")
            client_file.close()
            return True

    # 定义读取用户已获得公钥数据文件的方法
    @staticmethod
    def get_client_get_key_list_file(self_name):
        # 初始化相关列表
        Crypto_program.other_get_key_name_list.clear()
        Crypto_program.other_get_time_key_list.clear()
        Crypto_program.other_get_x3dh_key_list.clear()
        Crypto_program.self_get_x3dh_time_key_list.clear()
        client_get_key_list_file_name = str(self_name) + File_program.client_get_key_list_file_name_part
        if os.path.exists(client_get_key_list_file_name):  # 检测该用户文件数据是否存在
            client_get_key_list_file = open(client_get_key_list_file_name, "r")  # 以只读模式打开用户文件
            client_get_key_list_content = client_get_key_list_file.readlines()
            client_get_key_list_file.close()
            key_num = len(client_get_key_list_content)
            for i in range(0, key_num):
                if i % 5 == 0:  # 用户名
                    Crypto_program.other_get_key_name_list.append(client_get_key_list_content[i].strip("\n"))
                elif i % 5 == 1:  # 一次性公钥
                    Crypto_program.other_get_time_key_list.append(client_get_key_list_content[i].strip("\n"))
                elif i % 5 == 2:  # x3dh 生成密钥
                    Crypto_program.other_get_x3dh_key_list.append(client_get_key_list_content[i].strip("\n"))
                elif i % 5 == 3:  # 己方为获得x3dh密钥临时生成私钥对应的公钥
                    Crypto_program.self_get_x3dh_time_key_list.append(client_get_key_list_content[i].strip("\n"))
                else:
                    pass
            return True  # 返回处理结果
        else:
            return False

    # 定义修改用户已获得的公钥数据文件
    @staticmethod
    def update_client_get_key_list_file(sign_flag, self_name, other_name, other_time_public_key, share_x3dh_secret_key, time_public_key):  # 参数依次为：模式(1 添加，2 删除)，当前用户名，被获取公钥的主人名， 一次性公钥，共享密钥, 主动进行X3DH计算临时生成的公钥
        client_get_key_list_file_name = str(self_name) + File_program.client_get_key_list_file_name_part
        if str(sign_flag) == "1":
            # 将新的已获得公钥数据添加至相关列表中
            Crypto_program.other_get_key_name_list.append(other_name)
            Crypto_program.other_get_time_key_list.append(other_time_public_key)
            Crypto_program.other_get_x3dh_key_list.append(share_x3dh_secret_key)
            Crypto_program.self_get_x3dh_time_key_list.append(time_public_key)
            # 打开相关文件
            if os.path.exists(client_get_key_list_file_name):  # 检测该用户文件数据是否存在
                client_get_key_list_file = open(client_get_key_list_file_name, "a")  # 以追加模式打开用户数据文件
                client_get_key_list_file.write(other_name + "\n")
                client_get_key_list_file.write(other_time_public_key + "\n")
                client_get_key_list_file.write(share_x3dh_secret_key + "\n")
                client_get_key_list_file.write(str(time_public_key) + "\n")
                client_get_key_list_file.write("@file_should_division\n")
                client_get_key_list_file.close()
                return True
            else:
                return False
        elif str(sign_flag) == "2":
            # 将该数据从相关列表中删除
            Crypto_program.other_get_key_name_list.remove(other_name)
            Crypto_program.other_get_time_key_list.remove(other_time_public_key)
            Crypto_program.other_get_x3dh_key_list.remove(share_x3dh_secret_key)
            Crypto_program.self_get_x3dh_time_key_list.remove(time_public_key)
            # 打开相关文件
            if os.path.exists(client_get_key_list_file_name):  # 检测该用户文件数据是否存在
                client_get_key_list_file = open(client_get_key_list_file_name, "w")  # 以重写模式打开用户数据文件
                data_num = len(Crypto_program.other_get_key_name_list)
                for i in range(0, data_num):
                    client_get_key_list_file.write(Crypto_program.other_get_key_name_list[i] + "\n")
                    client_get_key_list_file.write(Crypto_program.other_get_time_key_list[i] + "\n")
                    client_get_key_list_file.write(Crypto_program.other_get_x3dh_key_list[i] + "\n")
                    client_get_key_list_file.write(str(Crypto_program.self_get_x3dh_time_key_list[i]) + "\n")
                    client_get_key_list_file.write("@file_should_division\n")
                client_get_key_list_file.close()
                return True
            else:
                return False
        else:
            return False


# 创建图形界面类
class Window_program(object):
    def __init__(self):
        super().__init__()

    # 以下为窗口的相关参数
    screen_size = "1000x800+100+100"
    name = "基于X3DH的开发测试程序(客户端) v3.50"
    # 以下为图形化界面参数
    # 初始界面容器
    start_frame = ""
    # 注册界面容器
    register_frame = ""
    # 登录界面容器
    login_frame = ""
    # 用户界面容器
    interface_frame = ""
    # 公共聊天室界面容器
    public_chat_room_frame = ""
    # 客户端生成公私钥对界面容器
    interface_key_frame = ""
    # 服务端公钥展示界面容器
    show_sever_key_frame = ""
    # 客户端公钥展示界面容器
    show_client_key_frame = ""
    # 等待模式界面容器
    wait_mode_frame = ""
    # 聊天室模式 初始界面容器
    private_chat_mode_frame = ""
    # 聊天室模式  房主界面容器
    private_chat_host_frame = ""
    # 聊天室模式  成员界面容器
    private_chat_guest_frame = ""

    # 创建工具栏的方法
    @staticmethod
    def create_menu():
        # 创建工具栏
        root_menu = tk.Menu(root_window, )
        root_window.config(menu=root_menu)
        root_menu.add_command(label="帮助", command=Window_program.help_function)
        root_menu.add_command(label="关于", command=Window_program.about_function)
        root_menu.add_command(label="其他", command=Window_program.other_function)

    # 以下均为实现工具栏中的方法
    @staticmethod
    def help_function():
        messagebox.showinfo("帮助", "此版本仅仅完成了基本功能，若遇到以下问题: \n 1 退出按键失效：使用任务管理器将其关闭 \n 2 通信失败；请确保通信双方使用同一对系统")

    @staticmethod
    def about_function():
        messagebox.showinfo("关于", "这是基于X3DH协议的加密通信系统(客户端) v3.50 \n 作者: 信安21-1 任磊 \n 完成日期: 2023-10-？？")

    @staticmethod
    def other_function():
        messagebox.showinfo("其他", "此版本尚且存在些许bug，如果可以的话，当多个用户使用时，请在客户之间交替使用时，彻底重启该客户端系统后，再登录其他用户")

    @staticmethod
    def deny_exit():
        messagebox.showwarning("警告", "您不能从此处退出客户端！", )

    # 定义导入图片并调整图片尺寸的方法
    @staticmethod
    def get_img(file, flag, width, height):
        if flag is True:  # 判断是否需要改变图像尺寸
            img = Image.open(file).resize((width, height))
        else:
            img = Image.open(file)
        return ImageTk.PhotoImage(img)

    # 定义清空根窗口的方法
    @staticmethod
    def clear_root_window():
        for item in root_window:
            item.destroy()

    # 定义清空容器内组件的方法
    @staticmethod
    def clear_frame(frame):
        for item in frame:
            item.destroy()


# 创建主程序类
class Main_program(object):
    def __init__(self):
        super().__init__()

    version = "3.50"  # 版本号
    name = ""  # 用户昵称暂存变量
    password = ""  # 用户密码暂存变量

    # 系统入口即初始界面的方法
    @staticmethod
    def start_application():
        # 调用初始化数据的方法
        Main_program.init_all_data()
        # 主菜单界面容器
        Window_program.start_frame = tk.Frame(root_window, relief="raised", bd=3, height=500, width=400)
        Window_program.start_frame.place(anchor="center", relx=0.5, rely=0.5)
        # 开启时的显示语
        tk.Label(Window_program.start_frame, text="基于X3DH的开发测试程序(带界面客户端)v3.50", font=("kaiti", 18), padx=25, pady=20, anchor="center").grid(row=0, padx=10, pady=10)
        tk.Label(Window_program.start_frame, text="请选择操作:", font=("kaiti", 18), padx=25, pady=20, anchor="center").grid(row=1, padx=10, pady=10)
        # 登录按钮
        tk.Button(Window_program.start_frame, text="登录", fg="blue", font=("黑体", 15), anchor="center", padx=15, pady=10, command=Main_program.start_window_to_login_window).grid(row=2, padx=10, pady=10)
        # 注册按钮
        tk.Button(Window_program.start_frame, text="注册", fg="blue", font=("黑体", 15), anchor="center", padx=15, pady=10, command=Main_program.start_window_to_register_window).grid(row=3, padx=10, pady=10)
        # 退出按钮
        tk.Button(Window_program.start_frame, text="退出", fg="red", font=('黑体', 15), anchor="center", padx=15, pady=10, command=Main_program.close_program).grid(row=4, padx=10, pady=10)

    # 初始界面转向其他功能界面的方法
    @staticmethod
    def start_window_to_login_window():
        Window_program.start_frame.destroy()
        Connection_program.login_window()

    @staticmethod
    def start_window_to_register_window():
        Window_program.start_frame.destroy()
        Connection_program.register_window()

    # 定义关闭客户端的方法
    @staticmethod
    def close_program():
        root_window.destroy()
        exit()

    # 定义初始化系统内数据的方法
    @staticmethod
    def init_all_data():
        Main_program.name = ""
        Main_program.password = ""
        Connection_program.hang_key_person_list = []
        Crypto_program.sys_time_key = None  # 系统默认生成的临时通行密钥
        Crypto_program.self_sm2_public_key = ""  # 用户SM2公钥
        Crypto_program.self_sm2_private_key = ""  # 用户SM2私钥
        Crypto_program.self_private_key = ""  # 用户的身份私钥
        Crypto_program.self_public_key = ""  # 用户的身份公钥
        Crypto_program.self_share_public_key = ""  # 用户的预共享公钥
        Crypto_program.self_share_private_key = ""  # 用户的预共享公钥的私钥
        Crypto_program.self_share_public_key_sign = "NONE"  # 用户的预共享公钥的签名
        Crypto_program.self_time_key_list = []  # 用户一次性公私钥对列表
        Crypto_program.x3dh_p = 0  # 默认情况下，取默认值
        Crypto_program.x3dh_g = 0  # 默认情况下，取默认值
        Crypto_program.x3dh_q = 0  # 默认情况下，取默认值

    # 清空当前屏幕的方法
    @staticmethod
    def clear_screen():
        # pyautogui.hotkey("Ctrl", "Shift", "Tab")
        pass


# 创建根窗口
root_window = tk.Tk()  # 设置根窗口
root_window.title(Window_program.name)  # 设置窗口名称
root_window.geometry(Window_program.screen_size)  # 设置窗口大小
root_window.config(background="azure")  # 设置背景颜色
root_window.attributes("-topmost", 1)  # 将窗口显示在最高级
Window_program.create_menu()  # 创建根界面工具栏
root_window.resizable(False, False)  # 设置使窗口大小不可变
root_window.protocol("WM_DELETE_WINDOW", Window_program.deny_exit)  # 设置限制，防止客户端非法退出运行
# 设置背景图片
canvas_window = tk.Canvas(root_window, width=1000, height=800)
bg = Window_program.get_img("星空图1.webp", True, 1000, 800)
canvas_window.create_image(500, 400, image=bg)
canvas_window.pack()


# 启动程序的入口
Main_program.start_application()


root_window.mainloop()